Solved

writing my own Message-handler in delphi

Posted on 1998-12-06
29
216 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
 
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
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

760 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

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now