Solved

writing my own Message-handler in delphi

Posted on 1998-12-06
29
223 Views
Last Modified: 2010-04-04
i'm building a component that should capture the WM_GETMINMAXINFO message, and prevent the form, where the component resides on, from being made smaller than a (any) number.

hou would i do this
0
Comment
Question by:topkapi
  • 13
  • 8
  • 5
  • +1
29 Comments
 
LVL 17

Expert Comment

by:inthe
ID: 1349515
Hi TopKapi

procedure TForm1.WMGetMinMaxInfo(var msg: TWMGetMinMaxInfo);
begin
  with msg.MinMaxInfo^ do  begin
    ptMaxSize   := Point(300, 300);
    ptMinTrackSize  := Point(100, 100);
    ptMaxTrackSize := Point(300, 300);
  end;
end;

Barry
0
 

Author Comment

by:topkapi
ID: 1349516
thanks for the quick reply, but the whole question was:

Can you show me how i would do this in a _component_ on a form?

thanks
0
 
LVL 17

Expert Comment

by:inthe
ID: 1349517
ok dude im on it but wont be back for a while :-)

0
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 10

Expert Comment

by:viktornet
ID: 1349518
Try something like this...

TComp = class(TComponent)
{...}
public
  procedure WMGetMinMaxInfo(var msg: TWMGetMinMaxInfo);message     WM_GETMINMAXINFO;
{...}
procedure TComp.WMGetMinMaxInfo(var msg: TWMGetMinMaxInfo);
begin
       with msg.MinMaxInfo^ do  begin
         ptMaxSize   := Point(300, 300);
         ptMinTrackSize  := Point(100, 100);
         ptMaxTrackSize := Point(300, 300);
       end;
end;

Try it out and tell me how it works..

Cheers,
Viktor
0
 

Author Comment

by:topkapi
ID: 1349519
how does that function get executed? i mean, you can resize the form till you die, but still nothing happens!

(excuse my ignorance)
0
 

Author Comment

by:topkapi
ID: 1349520
for your information, i could post the source as it is so far:

----------------cut-here---8<----------------------------------
unit FormSizeControl;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls,
  Forms, Dialogs;

type
  TFormSizeControl = class(TComponent)

  private
    { Private declarations }

    // coordinates for min en max size of form
    MinPoint  : TPoint;
    MaxPoint  : TPoint;

    // property handlers
    procedure setMinWidth(I: Integer);
    function  getMinWidth: Integer;

    procedure setMinHeigth(I: Integer);
    function  getMinHeigth: Integer;

    procedure setMaxWidth(I: Integer);
    function  getMaxWidth: Integer;

    procedure setMaxHeigth(I: Integer);
    function  getMaxHeigth: Integer;

  published
    { Published declarations }

    // Constructor / Destructor
    constructor Create(AOwner: TComponent); override;
    Destructor  Destroy; override;

    // Property definitions
    property MinWidth  : Integer read getMinWidth   write setMinWidth   default 0;
    property MinHeight : Integer read getMinHeigth  write setMinHeigth  default 0;
    property MaxWidth  : Integer read getMaxWidth   write setMaxWidth   default 0;
    property MaxHeight : Integer read getMaxHeigth  write setMaxHeigth  default 0;

  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Remco', [TFormSizeControl]);
end;


//==[Constructor / Destructor]==================================================
constructor TFormSizeControl.Create(AOwner: TComponent);
begin
  Inherited;
  //
end;

Destructor  TFormSizeControl.Destroy;
begin
  //
  Inherited;
end;




//==[get and set min/max width & heigth property's]=============================
procedure TFormSizeControl.setMinWidth(I: Integer);
begin
  I := Abs(I);

  MinPoint.X := I;

  if((I > MaxPoint.X) and not (MaxPoint.X = 0))then
    MaxPoint.X := I;
end;

function  TFormSizeControl.getMinWidth: Integer;
begin
  Result := MinPoint.X;
end;

procedure TFormSizeControl.setMinHeigth(I: Integer);
begin
  I := Abs(I);

  MinPoint.Y := I;

  if((I > MaxPoint.Y) and not (MaxPoint.Y = 0))then
    MaxPoint.Y := I;
end;

function  TFormSizeControl.getMinHeigth: Integer;
begin
  Result := MinPoint.Y;
end;

procedure TFormSizeControl.setMaxWidth(I: Integer);
begin
  I := Abs(I);

  MaxPoint.X := I;

  if((I < MinPoint.X) and not (I = 0)) then
    MinPoint.X := I;
end;

function  TFormSizeControl.getMaxWidth: Integer;
begin
  Result := MaxPoint.X;
end;

procedure TFormSizeControl.setMaxHeigth(I: Integer);
begin
  I := Abs(I);

  MaxPoint.Y := I;

  if((I < MinPoint.Y) and not (I = 0)) then
    MinPoint.Y := I;
end;

function  TFormSizeControl.getMaxHeigth: Integer;
begin
  Result := MaxPoint.Y;
end;

end.

--------------end-here--->8------------------------------------

maybe this will help.

0
 
LVL 10

Expert Comment

by:viktornet
ID: 1349521
Did you try doing what I told ya??
0
 
LVL 20

Accepted Solution

by:
Madshi earned 200 total points
ID: 1349522
Hello guys and girls (if any :-(),

you must answer the WM_GETMINMAXINFO of the Form, not of your component. That's why Viktor's code is not working, I think.

var prevWndProc : integer = 0;
    mmi         : TMinMaxInfo;
function MyHookProc(window,msg: cardinal; wparam,lparam: integer) : integer; stdcall;
begin
  if msg=WM_GETMINMAXINFO then begin
    with PMinMaxInfo(lparam)^ do begin
      ptMaxSize:=mmi.ptMaxSize;
      ptMaxPosition:=mmi.ptMaxPosition;
      ptMinTrackSize:=mmi.ptMinTrackSize;
      ptMaxTrackSize:=mmi.ptMaxTrackSize;
    end;
    result:=0;
  end else result:=CallWindowProc(pointer(prevWndProc),window,msg,wparam,lparam);
end;

procedure HookMyParentWindow(form: TForm);
begin
  if (form=nil) or (prevWndProc<>0) then exit;
  prevWndProc:=GetWindowLong(form.handle,GWL_WNDPROC);
  SetWindowLong(form.handle,GWL_WNDPROC,integer(@MyHookProc));
end;

procedure UnhookMyParentWindow(form: TForm);
begin
  if (form=nil) or (prevWndProc=0) then exit;
  SetWindowLong(form.handle,GWL_WNDPROC,prevWndProc);
  prevWndProc:=0;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  mmi.ptMaxSize:=point(800,600);
  mmi.ptMaxPosition:=point(50,50);
  mmi.ptMinTrackSize:=point(300,300);
  mmi.ptMaxTrackSize:=point(800,600);
  HookMyParentWindow(Form1);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  UnHookMyParentWindow(Form1);
end;

Regards, Madshi.
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1349523
oh Madshi is right...

dammit, i didn't think of that b4 :(

Cheers,
Viktor
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1349524
i'm looking into it.

thanks so far.

Topkapi
0
 

Author Comment

by:topkapi
ID: 1349525
:-)
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1349526

well, i adjusted the code to:

-----------8<--------------------------------------------------

unit FormSizeControl;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls,
  Forms, Dialogs;

type
  TFormSizeControl = class(TComponent)

  private
    { Private declarations }

    // coordinates for min en max size of form
    MinPoint    : TPoint;
    MaxPoint    : TPoint;

    prevWndProc : integer;

    procedure HookMyParentWindow(form: TForm);
    procedure UnhookMyParentWindow(form: TForm);
    function  MyHookProc(window ,msg: cardinal; wparam, lparam: integer): integer; stdcall;

    {...}

  published
    { Published declarations }

    // Constructor / Destructor
    constructor Create(AOwner: TComponent); override;
    Destructor  Destroy; override;

    {...}

  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Remco', [TFormSizeControl]);
end;


//==[Constructor / Destructor]==================================================
constructor TFormSizeControl.Create(AOwner: TComponent);
begin
  Inherited;
  prevWndProc := 0;
  HookMyParentWindow(TForm(AOwner));
end;

Destructor  TFormSizeControl.Destroy;
begin
  UnHookMyParentWindow(TForm(Owner));
  Inherited;
end;

procedure TFormSizeControl.HookMyParentWindow(Form: TForm);
begin
  if((Form = nil) or (prevWndProc <> 0)) then
    exit;

  prevWndProc := GetWindowLong(Form.Handle, GWL_WNDPROC);
  SetWindowLong(Form.Handle, GWL_WNDPROC, Integer(@TFormSizeControl.MyHookProc));
end;

procedure TFormSizeControl.UnhookMyParentWindow(Form: TForm);
begin
  if((Form = nil) or (prevWndProc = 0)) then
    exit;

  SetWindowLong(Form.Handle, GWL_WNDPROC, prevWndProc);
  prevWndProc := 0;
end;

function TFormSizeControl.MyHookProc(Window, Msg: cardinal; Wparam, Lparam: Integer): Integer; stdcall;
begin
  if(Msg = WM_GETMINMAXINFO)then
  begin

    with PMinMaxInfo(Lparam)^ do
    begin
      ptMaxSize      := MaxPoint;
      //ptMaxPosition  := ptMaxPosition;
      ptMinTrackSize := MaxPoint; // mmi.ptMinTrackSize;
      ptMaxTrackSize := MaxPoint; // mmi.ptMaxTrackSize;
    end;

    Result := 0;
  end
  else
    Result := CallWindowProc(Pointer(prevWndProc), Window, Msg, Wparam, Lparam);
end;

{...}

end.

--------------------->8------------------------------

It compiles fine,
but when i drop the component on a form i get an acces violation.

must be in the Constructor somewhere, but i'm new to this, so please explain.....

Topkapi
0
 

Author Comment

by:topkapi
ID: 1349527
Hey, what's that? In my explorer it looks like Topkapi has written under my name! Do you see that, too? Looks like an EE-bug. Probably, because I've tried to write a comment at the same time as Topkapi...
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1349528
who!

those entrys don't seem to be going right.

all the names are messed up, aand my code isn't there.


0
 
LVL 20

Expert Comment

by:Madshi
ID: 1349529
You can't simple put this MyHookProc into your component, because then it's:
  function MyHookProc(...) : integer; stdcall OF OBJECT;
Now it has a hidden "self" parameter. And that's not compatible to the format, that Windows wants to have. So you can put all the other functions in your component, but the MyHookProc procedure must be stand alone.

Regards, Madshi.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1349530
Uaaaaa!!! It seems that EE is crashing around...

It's me (Madshi) not topkapi...

That's really fun. I'll go and tell the EE-team about this problem!

Regards, Madshi.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1349531
It seems that it is working again...  :-)
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1349532
Oh, no. Seems that the last comment is not shown until a new comment comes that is again not shown until a new comment comes...
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1349533
Dummy comment just to show the other one...
0
 
LVL 17

Expert Comment

by:inthe
ID: 1349534
And another dummy...
0
 
LVL 17

Expert Comment

by:inthe
ID: 1349535
thanks madshi
 i too have been trying to do it like my original awnswer and as viktor said but buggered if i could get it to work :-( now i see why
i think i need a book on component writing, know of any good ones ?all the books i got only do like one chapter or so on it
Regards Barry

0
 

Author Comment

by:topkapi
ID: 1349536
¤¤¤¤hello im a comment¤¤¤¤
0
 
LVL 17

Expert Comment

by:inthe
ID: 1349537
Now my comments are not only under the wrong name, they don't appear at all...
0
 

Author Comment

by:topkapi
ID: 1349538


 my head hurts  :-)

¤B¤
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1349539
If only can explain to me what the following code exactly do, i would be very gratefull. i can't find them in Delphi help. guess there api-calls of some sort?

    with PMinMaxInfo(lparam)^ do begin
      ptMaxSize:=mmi.ptMaxSize;
      ptMaxPosition:=mmi.ptMaxPosition;
      ptMinTrackSize:=mmi.ptMinTrackSize;
      ptMaxTrackSize:=mmi.ptMaxTrackSize;
    end;
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1349540
Hi Barry,

don't know any good component writing books...  :-(
If you want to learn something you should just try to understand the delphi components (of course you need the professional or client/server version, otherwise you won't have the sources). That's the way I learned component writing.
But I think this question was mainly about how to make the WM_GETMINMAXINFO message working. So I think this was more a win32 question than a component writing question. The problem with your answer was only, that you handled the wrong window.

Regards, Madshi.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1349541
Ok, I don't know who asked this question from Sunday, December 06 1998 - 11:01PM, but it doesn't matter...   :-)))

If you look at the documentation of the WM_GETMINMAXINFO, you'll find:
WM_GETMINMAXINFO  
lpmmi = (LPMINMAXINFO) lParam; // address of structure

And if you read the rest of the documentation you'll find that the lParam value is a pointer to an already allocated and already with standard values filled MINMAXINFO structure. The Type "PMinMaxInfo" that I used in my sources is the Delphi pointer type of this MINMAXINFO structure.
This is what my sources does: It converts the lParam pointer into a PMinMaxInfo pointer, then fills all the values in the structure (that is referenced by lParam respectivly PMinMaxInfo(lParam)). The mmi variable is just a kind of static parameter that contains all the point values you want to set.
Everything clear now?

Regards, Madshi.
0
 

Author Comment

by:topkapi
ID: 1349542
Dummy...
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1349543
test comment
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Established in 1997, Technology Architects has become one of the most reputable technology solutions companies in the country. TA have been providing businesses with cost effective state-of-the-art solutions and unparalleled service that is designed…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

828 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question