Lazarus

Programming => General => Topic started by: KarenT on May 21, 2017, 08:37:09 pm

Title: SetWindowPos problem
Post by: KarenT on May 21, 2017, 08:37:09 pm
Sorry to be a pest with basic questions, but I can't get this to compile and searching has not found me a solution.

Code: Pascal  [Select][+][-]
  1.   SetWindowPos(Self.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE
  2.      or   SWP_NOACTIVATE);
  3.  

I get "Identifier not found: SetWindowPos"

I checked the Code Browser and it shows it in LCL and LCLBase.

LCL is already in the "Uses" and LCLBase shows "Cannot find LCLBase" if I add that in, so stumped I be.

What do I need to add to a "Uses" clause?
Title: Re: SetWindowPos problem
Post by: Thaddy on May 21, 2017, 08:53:15 pm
If setWindowPos is in lclintf or its include files (check that!) add just lclintf.

If it isn't:
It is a windows specific function from the windows API for which there is no X-platform direct equivalen availablet.
In such a case it is fine to add the windows (or a specific declaration ) unit, but you should document it is not cross platform.
Title: Re: SetWindowPos problem
Post by: sky_khan on May 21, 2017, 09:01:19 pm
Where did you get this ?

It looks like this only tries to set a window as topmost window,
in other words, it is same as TControl.BringToFront procedure.
Title: Re: SetWindowPos problem
Post by: Thaddy on May 21, 2017, 09:05:41 pm
in other words, it is same as TControl.BringToFront procedure.

Nope. BringToFront affects focus. This is a very old and bad Delphi hack to show a form or dialog window topmost in the left-top without receiving focus.
But it is a valid WINAPI call.

The proper fix is to have that form include the StayOnTop property. Which is also cross-platform and Delphi compatible..
Title: Re: SetWindowPos problem
Post by: GetMem on May 21, 2017, 09:09:23 pm
@KarenT
This is cross platform:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.   Self.Left := 0;
  4.   Self.Top := 0;
  5.   Self.FormStyle := fsSystemStayOnTop;
  6. end;
Title: Re: SetWindowPos problem
Post by: Thaddy on May 21, 2017, 09:12:55 pm
Exactly. Tnx GetMem.

Note that fsSystemStayOnTop is not available in Delphi. Hence I suggested StayOnTop.
Title: Re: SetWindowPos problem
Post by: RAW on May 22, 2017, 12:17:19 am
Isn't it better to use SETBOUNDS only once ???
Code: Pascal  [Select][+][-]
  1.  SetBounds(0, 0, Width, Height);

As far as I know LEFT and TOP and WIDTH and HEIGHT calls SETBOUNDS...  :P
Title: Re: SetWindowPos problem
Post by: GetMem on May 22, 2017, 05:37:44 am
On second thought the OP doesn't want to move the window at all. Take a look at the parameters: SWP_NOSIZE or SWP_NOMOVE or  SWP_NOACTIVATE. So the solution is:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.    Self.FormStyle := fsSystemStayOnTop; //or fsStayOnTop
  4. end;
Title: Re: SetWindowPos problem
Post by: GetMem on May 22, 2017, 06:37:03 am
And just to prove that SetWindowPos is not completely useless(at least not under windows), below is a small demo that will set the Z order of an external application's main window. Make sure notepad is running first, then click button1:
Code: Pascal  [Select][+][-]
  1. uses JwaWindows, jwatlhelp32;
  2.  
  3. function GetProcessMainWindow(const PID: DWORD; const wFirstHandle: HWND): HWND;
  4. var
  5.   wHandle: HWND;
  6.   ProcID: DWord;
  7. begin
  8.   Result := 0;
  9.   wHandle := GetWindow(wFirstHandle, GW_HWNDFIRST);
  10.   while wHandle > 0 do
  11.   begin
  12.     GetWindowThreadProcessID(wHandle, @ProcID);
  13.     if (ProcID = PID) and (GetParent(wHandle) = 0) and (IsWindowVisible(wHandle)) then
  14.     begin
  15.       Result := wHandle;
  16.       Break;
  17.     end;
  18.     wHandle := GetWindow(wHandle, GW_HWNDNEXT);
  19.   end;
  20. end;
  21.  
  22. function FindProcessByName(const ProcName:string): DWORD;
  23. var
  24.   Proc: TPROCESSENTRY32;
  25.   hSnap: HWND;
  26.   Looper: BOOL;
  27. begin
  28.   Result := 0;
  29.   Proc.dwSize := SizeOf(Proc);
  30.   hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
  31.   Looper := Process32First(hSnap, Proc);
  32.   while Integer(Looper) <> 0 do
  33.   begin
  34.     if UpperCase(ExtractFileName(proc.szExeFile)) = UpperCase(ProcName) then
  35.     begin
  36.       Result:=proc.th32ProcessID;
  37.       Break;
  38.     end;
  39.     Looper := Process32Next(hSnap, Proc);
  40.   end;
  41.   CloseHandle(hSnap);
  42. end;
  43.  
  44. procedure TForm1.Button1Click(Sender: TObject);
  45. var
  46.   PID: DWord;
  47.   wHandle: THandle;
  48. begin
  49.   PID := FindProcessByName('notepad.exe');
  50.   if PID <> 0 then
  51.   begin
  52.     wHandle := GetProcessMainWindow(PID, Form1.Handle);
  53.     if wHandle <> 0 then
  54.       SetWindowPos(wHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
  55.   end
  56.   else
  57.     MessageDlg('Notepad is not running.', mtInformation, [mbOk], 0);
  58. end;
Title: Re: SetWindowPos problem
Post by: KarenT on May 22, 2017, 07:05:18 pm
Thanks, when I read the Help it said (implied?) that "fsSystemStayOnTop" only stayed on top of all other forms in that program. I want it to stay on top of everything and all the time it is open.

But, I just tried setting the FormStyle to "fsSystemStayOnTop" and it seems to do what I want. So, I either misread the Help or the Help is... :)
TinyPortal © 2005-2018