Link to home
Start Free TrialLog in
Avatar of craig_capel
craig_capel

asked on

move a form

The question is as follows:

In Swag if you have seen it, one of the snippits trys to
show you how to move a form without clicking on the blue bar
at the top, what it says to do is fool windows into thinking
the blue bar is the form by using inherit, anyhow, i tried
and tried and tried to get it to work with delphi 4... i have
almost given up...


So does anyone here know what i am onabout? if you do could
someone show me how to do this? PLEASE?? Thanks.... ok and
if you use winamp heres my free code back to you....

i have been working on an interface for winamp, externally and
this is what i have come up with so far, all i now want to do is
move it, as my questions asks :)


unit winampstalker1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls, Menus, shellapi;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Timer1: TTimer;
    PopupMenu1: TPopupMenu;
    Close1: TMenuItem;
    CloseandCloseWinamp1: TMenuItem;
    Move1: TMenuItem;
    PlayAMusicFile1: TMenuItem;
    OpenDialog1: TOpenDialog;
    HideWinamp1: TMenuItem;
    ShowWinamp1: TMenuItem;
    procedure Timer1Timer(Sender: TObject);
    procedure PlayAMusicFile1Click(Sender: TObject);
    procedure HideWinamp1Click(Sender: TObject);
    procedure ShowWinamp1Click(Sender: TObject);
    procedure Close1Click(Sender: TObject);
    procedure Move1Click(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure CloseandCloseWinamp1Click(Sender: TObject);
    procedure Label1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Label1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure Label1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
 mousedownvar, wellwhat: boolean;
i1 : integer;
passfile,tmp1,s1,s2 : string;
wnd: hwnd;

tmp_chr: char;
n: integer;
len: integer;


implementation

{$R *.DFM}

procedure TForm1.Timer1Timer(Sender: TObject);
begin
wnd:=findwindow('winamp v1.x',nil);
if wnd=null then close;
i1 := SendMessage(wnd, WM_GETTEXTLENGTH, 0, 0);
SetLength(s1, i1 + 1);
SetLength(s1, SendMessage(wnd, WM_GETTEXT, i1 + 1,integer(s1)));
if s1<>s2 then
 begin
 wellwhat:=false;
  label1.caption:= s1+' ';
 end;
 s2:=s1;
 if (length(s1)<=1) and (wellwhat=false) then
   begin
     wellwhat:=true;
      label1.caption:='Winamp Not Running!!!  ';
   end;
form1.width:=label1.Width;

  tmp1:=label1.caption;
  len:=length(tmp1);
  tmp_chr:=tmp1[1];
  for n:=1 to len-1 do
     begin
        tmp1[n]:=tmp1[n+1];
     end;
   tmp1[len]:=tmp_chr;
label1.caption:=tmp1;
end;

procedure TForm1.PlayAMusicFile1Click(Sender: TObject);
begin
opendialog1.execute;
passfile:=opendialog1.filename;
shellExecute(handle,'open',pchar(passfile),'','',0);
end;

procedure TForm1.HideWinamp1Click(Sender: TObject);
var
 wnd2: hwnd;
begin
   wnd2:=findwindow('winamp V1.x',nil);
   showwindow(wnd2,sw_hide);

end;

procedure TForm1.ShowWinamp1Click(Sender: TObject);
var
 wnd2: hwnd;
begin
   wnd2:=findwindow('winamp V1.x',nil);
   showwindow(wnd2,sw_show);
   showwindow(wnd2,sw_restore);
   setforegroundwindow(wnd2);
end;

procedure TForm1.Close1Click(Sender: TObject);
begin
close;
end;

procedure TForm1.Move1Click(Sender: TObject);
begin
  form1.borderstyle:=bsSizeable;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
form1.left:=23;
form1.top:=3;

end;

procedure TForm1.CloseandCloseWinamp1Click(Sender: TObject);
var
  wnd2: hwnd;
begin
   wnd2:=findwindow('winamp V1.x',nil);
   sendmessage(wnd2,wm_close,0,0);
   close;
end;

procedure TForm1.Label1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
 mousedownvar:=true;
end;

procedure TForm1.Label1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
 if mousedownvar=true then
   begin
      form1.top:=x;
      form1.Left:=y;
   end;

end;

procedure TForm1.Label1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
mousedownvar:=false;
end;

end.


{
object Form1: TForm1
  Left = 285
  Top = 132
  BorderStyle = bsNone
  Caption = 'Winamp EXT'
  ClientHeight = 13
  ClientWidth = 193
  Color = clLime
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  FormStyle = fsStayOnTop
  OldCreateOrder = False
  PopupMenu = PopupMenu1
  OnActivate = FormActivate
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 0
    Top = 0
    Width = 32
    Height = 13
    Caption = 'Label1'
    Color = 8454143
    ParentColor = False
    OnMouseDown = Label1MouseDown
    OnMouseMove = Label1MouseMove
    OnMouseUp = Label1MouseUp
  end
  object Timer1: TTimer
    Interval = 400
    OnTimer = Timer1Timer
    Left = 142
    Top = 65532
  end
  object PopupMenu1: TPopupMenu
    Left = 164
    object PlayAMusicFile1: TMenuItem
      Caption = 'Play A Music File'
      OnClick = PlayAMusicFile1Click
    end
    object HideWinamp1: TMenuItem
      Caption = 'Hide Winamp'
      OnClick = HideWinamp1Click
    end
    object ShowWinamp1: TMenuItem
      Caption = 'Show Winamp'
      OnClick = ShowWinamp1Click
    end
    object CloseandCloseWinamp1: TMenuItem
      Caption = 'Exit and Close Winamp'
      OnClick = CloseandCloseWinamp1Click
    end
    object Move1: TMenuItem
      Caption = 'Move '
      Enabled = False
      OnClick = Move1Click
    end
    object Close1: TMenuItem
      Caption = 'Exit'
      OnClick = Close1Click
    end
  end
  object OpenDialog1: TOpenDialog
    DefaultExt = '.mp3'
    Filter = 'Mpeg File|*.mp3|All Files (*.*)|*.*'
    Left = 116
  end
end
}

and the info i added, i hope some one other than me finds it of use
and if you do you use it just mention me somewhere :) thanks again.....

Craig C.
Avatar of kretzschmar
kretzschmar
Flag of Germany image

hi craig,

i guess you need something like this:

unit test_u;

interface

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

type
  TForm2 = class(TForm)
  private
    { Private declarations }
    Procedure WMNCHITTEST(var Message : TMessage); message WM_NCHITTEST;
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.DFM}

Procedure TForm2.WMNCHITTEST(var Message : TMessage);
begin
  DefaultHandler(Message);
  if Message.Result = HTCLIENT then
    Message.Result := HTCAPTION;
end;


end.

meikl

ps: have not done a closer look to your code
Avatar of craig_capel
craig_capel

ASKER

Nope, just as before, compiler errors with that winchest thing


 Procedure WMNCHITTEST(var Message : TMessage); message WM_NCHITTEST;

that does not compile


[Error] Unit1.pas(28): Undeclared identifier: 'Message'
[Error] Unit1.pas(29): 'THEN' expected but identifier 'Result' found
[Error] Unit1.pas(35): Statement expected but end of file found
[Error] Unit1.pas(14): Unsatisfied forward or external declaration: 'TForm1.WMNCHITTEST'
[Fatal Error] Project2.dpr(5): Could not compile used unit 'Unit1.pas'

as you can see....
message is a reserved word, try changing the proc param list to:

Procedure WMNCHITTEST(var Msg : TMessage); message WM_NCHITTEST;

Gl
Mike

hi craig,

? did you checked the uses clause ?
seemed you've pasted something wrong

try again

meikl

ps.: which delphi version do you use?
yup edey,

you could be right
(my d5 version didn't say that message
will be reserved in this context, but
lower versions could do this)

the correction

unit test_u;

interface

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

type
  TForm2 = class(TForm)
  private
    { Private declarations }
    Procedure WMNCHITTEST(var Msg : TMessage); message WM_NCHITTEST;
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.DFM}

Procedure TForm2.WMNCHITTEST(var Msg : TMessage);
begin
  DefaultHandler(Msg);
  if Msg.Result = HTClient then
    Msg.Result := HTCAPTION;
end;

end.

meikl
I have the ever-wonderful-super-fantastic opportunity to be stuck using D3 :( perhaps D5 will soon be in my future?  I guess I shouldn’t complain, though, as D3 is a far more enjoyable environment then most I have worked with :)


GL
Mike
Yep i use delphi 4.... and i have had no luck,still no change in responce from the compiler..... just that one line gives me this:

[Error] Unit1.pas(13): Unsatisfied forward or external declaration: 'TForm1.WMNCHITTEST'
[Fatal Error] Project1.dpr(5): Could not compile used unit 'Unit1.pas'


And the my source is this:

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
  private
    { Private declarations }
    Procedure WMNCHITTEST(var Msg2 : TMessage); message
                      WM_NCHITTEST;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}



end.


please please please do i have something wrong here? or maybee there is another way of doing what i need in Delphi 4...?  thanks again all for trying.

Craig C.
ASKER CERTIFIED SOLUTION
Avatar of kretzschmar
kretzschmar
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Well, i honestly tried that before and every combo i thought existed, but that last trick worked, well done!


:-)
glad that you get it work,
good luck again

meikl ;-)
oh no.... Dont know if you have tried doing this yourself but once you have done this it stops the popupmenu1 from working!!!!....  i have a little problem now :)

unit winampstalker1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls, Menus, shellapi;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Timer1: TTimer;
    PopupMenu1: TPopupMenu;
    Close1: TMenuItem;
    CloseandCloseWinamp1: TMenuItem;
    Move1: TMenuItem;
    PlayAMusicFile1: TMenuItem;
    OpenDialog1: TOpenDialog;
    HideWinamp1: TMenuItem;
    ShowWinamp1: TMenuItem;
    procedure Timer1Timer(Sender: TObject);
    procedure PlayAMusicFile1Click(Sender: TObject);
    procedure HideWinamp1Click(Sender: TObject);
    procedure ShowWinamp1Click(Sender: TObject);
    procedure Close1Click(Sender: TObject);
    procedure Move1Click(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure CloseandCloseWinamp1Click(Sender: TObject);
    procedure Label1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Label1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure Label1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }

    Procedure WMNCHITTEST(var Msg : TMessage); message
                                            WM_NCHITTEST;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
 mousedownvar, wellwhat: boolean;
i1 : integer;
passfile,tmp1,s1,s2 : string;
wnd: hwnd;

tmp_chr: char;
n: integer;
len: integer;


implementation

{$R *.DFM}

Procedure TForm1.WMNCHITTEST(var Msg : TMessage);
                      begin
                        DefaultHandler(Msg);
                        if Msg.Result = HTClient then
                          Msg.Result := HTCAPTION;
                      end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
wnd:=findwindow('winamp v1.x',nil);
if wnd=null then close;
i1 := SendMessage(wnd, WM_GETTEXTLENGTH, 0, 0);
SetLength(s1, i1 + 1);
SetLength(s1, SendMessage(wnd, WM_GETTEXT, i1 + 1,integer(s1)));
if s1<>s2 then
 begin
 wellwhat:=false;
  label1.caption:= s1+' ';
 end;
 s2:=s1;
 if (length(s1)<=1) and (wellwhat=false) then
   begin
     wellwhat:=true;
      label1.caption:='Winamp Not Running!!!  ';
   end;
form1.width:=label1.Width;

  tmp1:=label1.caption;
  len:=length(tmp1);
  tmp_chr:=tmp1[1];
  for n:=1 to len-1 do
     begin
        tmp1[n]:=tmp1[n+1];
     end;
   tmp1[len]:=tmp_chr;
label1.caption:=tmp1;
end;

procedure TForm1.PlayAMusicFile1Click(Sender: TObject);
begin
opendialog1.execute;
passfile:=opendialog1.filename;
shellExecute(handle,'open',pchar(passfile),'','',0);
end;

procedure TForm1.HideWinamp1Click(Sender: TObject);
var
 wnd2: hwnd;
begin
   wnd2:=findwindow('winamp V1.x',nil);
   showwindow(wnd2,sw_hide);

end;

procedure TForm1.ShowWinamp1Click(Sender: TObject);
var
 wnd2: hwnd;
begin
   wnd2:=findwindow('winamp V1.x',nil);
   showwindow(wnd2,sw_show);
   showwindow(wnd2,sw_restore);
   setforegroundwindow(wnd2);
end;

procedure TForm1.Close1Click(Sender: TObject);
begin
close;
end;

procedure TForm1.Move1Click(Sender: TObject);
begin
  form1.borderstyle:=bsSizeable;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
form1.left:=23;
form1.top:=3;

end;

procedure TForm1.CloseandCloseWinamp1Click(Sender: TObject);
var
  wnd2: hwnd;
begin
   wnd2:=findwindow('winamp V1.x',nil);
   sendmessage(wnd2,wm_close,0,0);
   close;
end;

procedure TForm1.Label1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
 mousedownvar:=true;
end;

procedure TForm1.Label1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
 if mousedownvar=true then
   begin
      form1.top:=x;
      form1.Left:=y;
   end;

end;

procedure TForm1.Label1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
mousedownvar:=false;
end;

end.

ok ok, if you know how to fix it, i will post some points up...
the problem lies here:

if Msg.Result = HTClient then
    Msg.Result := HTCAPTION;

this line ensures that ANY mouse event for the form will be treated as if it originated on the title bar.  What you need to do is decide which parts of the form you want to act as a title bar, and check msg.xpos and msg.ypos to see if the mouse event should be htCaption.

GL
Mike
an example, taken from a post-it notes sort of program I wrote:

procedure TSticky.doWMNCHITTEST(var msg : TWMNCHITTEST);
var
   pt : TPoint;
begin
     inherited;
     pt := screenToClient(point(msg.xpos,msg.ypos));
     if text.Visible then
     begin
          if (pt.y < kTitleBarHeight)and(width-pt.x > 3*kTitleBarHeight) then
             msg.result := htCaption
          else if (height-pt.y < kTitleBarHeight)and(width-pt.x < kTitleBarHeight) then
               msg.result := htBottomRight
          else if (pt.x <= (kTitleBarHeight div 4)) then
               msg.result := htLeft
          else if (width-pt.x <= (kTitleBarHeight div 4)) then
               msg.result := htRight
          else if (height-pt.y <= kTitleBarHeight) then
               msg.result := htBottom;
     end
     else
         if pt.x <= kTitleBarHeight then
            msg.result := htCaption;
end;



here kTitleBarHeight is the height of my "title bar" and allowances are made for some "buttons" on the top right, and sizing borders.

GL
Mike
i dont suppose this program you wrote had little yellow (or you could change the colour) and you could add to them to your screen and a little icon in the bottom right corner of your screen is this what i am describing sound like yours? if so i hve downloaded and i like it!....
ah,from what i can tell you do not have anything there to say... button click... i have played arround myself, the program is a form with a label on it, nothing else what so ever. all i need is a way of seeing if anything at all has been sent such as a wm_lbuttdown anything at all, otherwise move  the label, the form is a thin and as wide as the label is.....


i dont suppose this program you wrote had little yellow (or you could change the colour) and you could add to them to your screen and a little icon in the bottom right corner of your screen is this what i am describing sound like yours? if so i hve downloaded and i like it!....

Thanks for the help and program if it was yours (actually since i formtted and i have now lost the program anyway....)

Craig C.
I'm not sure what you mean, but the WN_NCHITTEST message can be checked for a number of things, from the win32.hlp:

Value      Location of hot spot
HTBORDER      In the border of a window that does not have a sizing border
HTBOTTOM      In the lower horizontal border of a window
HTBOTTOMLEFT      In the lower-left corner of a window border
HTBOTTOMRIGHT      In the lower-right corner of a window border
HTCAPTION      In a title bar
HTCLIENT      In a client area
HTERROR      On the screen background or on a dividing line between windows (same as HTNOWHERE, except that the DefWindowProc function produces a system beep to indicate an error)
HTGROWBOX      In a size box (same as HTSIZE)
HTHSCROLL      In a horizontal scroll bar
HTLEFT      In the left border of a window
HTMENU      In a menu
HTNOWHERE      On the screen background or on a dividing line between windows
HTREDUCE      In a Minimize button
HTRIGHT      In the right border of a window
HTSIZE      In a size box (same as HTGROWBOX)
HTSYSMENU      In a System menu or in a Close button in a child window
HTTOP      In the upper horizontal border of a window
HTTOPLEFT      In the upper-left corner of a window border
HTTOPRIGHT      In the upper right corner of a window border
HTTRANSPARENT      In a window currently covered by another window
HTVSCROLL      In the vertical scroll bar
HTZOOM      In a Maximize button



as for the program, mine does match your description, and if you would like a copy write me @ edey@hotmail.com


GL
Mike