[Windows] Form in Taskleiste

Für Fehler in Lazarus, um diese von anderen verifizieren zu lassen.

[Windows] Form in Taskleiste

Beitragvon compmgmt » 29. Dez 2018, 21:31 [Windows] Form in Taskleiste

Guten Abend allerseits,

da ich zwei Monitore besitze ist mir schon öfter aufgefallen dass bei allen meinen bisherigen GUI-Projekten die Anwendung/Main Form in der Taskleiste immer auf dem ersten Monitor angezeigt wird, auch wenn
1. die Form vom ersten auf den zweiten Monitor verschoben wird.
2. die Form auf dem zweiten Monitor erscheint (bspw. durch poDesigned).

Mit der WinApi Funktion MonitorFromWindow und dem Parameter MONITOR_DEFAULTTONEAREST erkennt windows korrekt dass sich die Form auf einem andern Monitor befindet (was ja auch Sinn macht, weil Windows alle Fenster managed).

Wie es sich auf andere Systeme bzw grafische Oberflächen auswirkt ist mir nicht bekannt.

Habt ihr ähnliche Erfahrungen oder ist das schon bekannt?

FPC 3.0.4 32-Bit
Laz 1.8.2 32-Bit
Win 10 Pro 64-Bit
Code: Alles auswählen
InitiateSystemShutdownExA(nil, nil, 0, true, false, $0005000F);
Have fun with this snippet ;)
compmgmt
 
Beiträge: 327
Registriert: 25. Nov 2015, 17:06
Wohnort: in der Nähe von Stuttgart
OS, Lazarus, FPC: Win 10 Pro | Lazarus 1.8.2 | FPC 3.0.4 | 
CPU-Target: i386 + x86_64
Nach oben

Beitragvon sstvmaster » 29. Dez 2018, 22:00 Re: [Windows] Form in Taskleiste

Hi, ist mir selber noch nicht aufgefallen bzw. habe ich noch nicht darauf geachtet. Probieren kann ich es aber erst wenn ich wieder auf Arbeit bin, da ich hier zuhause nur einen habe.

Habe mal gesucht wo die API in Lazarus steht, dazu habe ich folgendes gefunden:

In der customform.inc gibt es eine Funktion "GetMonitor":

Auszug:
Code: Alles auswählen
function TCustomForm.GetMonitor: TMonitor;
var
  ParentForm: TCustomForm;
begin
  if Assigned(Parent) then
  begin
    ParentForm := GetParentForm(Self);
    if Assigned(ParentForm) then
      Result := ParentForm.Monitor
    else
      Result := nil;
  end else
  begin
    if HandleAllocated then
      Result := Screen.MonitorFromWindow(Handle, mdNearest)
    else
      Result := Screen.MonitorFromPoint(point(Left,Top));
  end;
end;



LG und guten Rutsch, Maik
OS: Windows 7 32/64bit
Lazarus 1.8.4, 32bit
Lazarus 2.1.0 Trunk 3.3.1, 32bit
sstvmaster
 
Beiträge: 104
Registriert: 22. Okt 2016, 22:12
OS, Lazarus, FPC: Lazarus 2.0 RC3 + 2.1.0 Trunk 3.3.1 / Win32, Windows 7 32+64bit | 
CPU-Target: 32Bit
Nach oben

Beitragvon compmgmt » 30. Dez 2018, 09:23 Re: [Windows] Form in Taskleiste

Ich hatte die MonitorFromWindow Funktion direkt aus der User32.dll eingebunden da ich sie in der unit windows nicht gefunden habe, aber so wie du gehts natürlich einfacher.

Edit: Hab sie gefunden, ist in LCLIntf.
Code: Alles auswählen
InitiateSystemShutdownExA(nil, nil, 0, true, false, $0005000F);
Have fun with this snippet ;)
compmgmt
 
Beiträge: 327
Registriert: 25. Nov 2015, 17:06
Wohnort: in der Nähe von Stuttgart
OS, Lazarus, FPC: Win 10 Pro | Lazarus 1.8.2 | FPC 3.0.4 | 
CPU-Target: i386 + x86_64
Nach oben

Beitragvon compmgmt » 1. Jan 2019, 11:45 Re: [Windows] Form in Taskleiste

So, ich hab noch mal ein bisschen rumprobiert. Dazu wollte ich das Taskbar item mit ITaskbarList (un)sichtbar machen. Hier eine Möglichkeit wie es in Delphi funktionieren sollte (laut Delphi-Praxis Forenbeiträgen):
Code: Alles auswählen
...
uses shlobj, comobj, windows;
...
  private
    FTaskbar: ITaskbarList3;
...
 
procedure TWnd_Test.FormShow(Sender: TObject);
begin
  FTaskbar := CreateComObject(CLSID_TaskbarList) as ITaskbarList3;
  FTaskbar.HrInit;
end;
 
procedure TWnd_Test.Btn_AddTabClick(Sender: TObject);
begin
  FTaskbar.AddTab(Handle);
end;
 
procedure TWnd_Test.Btn_DeleteTabClick(Sender: TObject);
begin
  FTaskbar.DeleteTab(Handle);
end;
Für diesen Fall würde auch ITaskbarList (statt ITaskbarList3) reichen, aber darum geht es nicht. Beim Klick auf die Buttons passiert nichts.

Nun habe ich versucht das ganze bei fremden Fenstern zu machen: Mit Erfolg. Wenn man ein Application.Title Wert (nicht Form Caption!) mit FindWindow() sucht und das ganze macht funktioniert es. So kann man auch sein eigenes Taskbar Item (un)sichtbar machen. Dazu habe ich in die Form ein Edit namens Edt_AppTitle gepackt. Der von mir modifizierte Code hat funktioniert:
Code: Alles auswählen
procedure TWnd_Test.Btn_AddTabClick(Sender: TObject);
var
   h: HWND;
begin
   h := FindWindow(nil, LPCSTR(Edt_AppTitle.Caption));
   if h <> INVALID_HANDLE_VALUE then begin
      FTaskbar.AddTab(h);
      // um zu zeigen dass Form und Taskbar Item ein unterschiedliches Handle haben:
      Caption := 'Form: ' + IntToStr(Handle) + ' | Taskbar Item: ' + IntToStr(h);
   end;
end;
 
procedure TWnd_Test.Btn_DeleteTabClick(Sender: TObject);
var
   h: HWND;
begin
   h := FindWindow(nil, LPCSTR(Edt_AppTitle.Caption));
   if h <> INVALID_HANDLE_VALUE then begin
      FTaskbar.DeleteTab(h);
      // um zu zeigen dass Form und Taskbar Item ein unterschiedliches Handle haben:
      Caption := 'Form: ' + IntToStr(Handle) + ' | Taskbar Item: ' + IntToStr(h);
   end;
end;
Beim Eingeben des Application.Title Wertes in das Edit Feld und anschließendes Klicken auf die Button funktioniert es.

Das führt mich zu meiner Theorie: Das Taskbar Item von LCL Anwendungen ist gar nicht von der eigenen Form, sondern von einer im nicht sichtbaren Bereich befindlichen Form, was dazu führt dass Verschiebungen der eigenen Form auf den anderen Monitor zu keiner Änderung des Taskbar Items führen, weil dieses ja zu der unsichtbaren Form gehört, welche sich noch auf dem ersten Monitor befindet
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Code: Alles auswählen
InitiateSystemShutdownExA(nil, nil, 0, true, false, $0005000F);
Have fun with this snippet ;)
compmgmt
 
Beiträge: 327
Registriert: 25. Nov 2015, 17:06
Wohnort: in der Nähe von Stuttgart
OS, Lazarus, FPC: Win 10 Pro | Lazarus 1.8.2 | FPC 3.0.4 | 
CPU-Target: i386 + x86_64
Nach oben

Beitragvon compmgmt » 1. Jan 2019, 17:21 Re: [Windows] Form in Taskleiste

Ich bins nochmal. Hab es jetzt hinbekommen:
Code: Alles auswählen
uses ... {$ifdef mswindows}, windows {$endif};
...
  private
    {$ifdef mswindows}
      FTaskbarItemHandle: HWND;
    {$endif}
...
procedure TWnd_Test.FormChangeBounds(Sender: TObject);
begin
  {$ifdef mswindows}
    if FTaskbarItemHandle <> INVALID_HANDLE_VALUE then begin
      SetWindowPos(FTaskbarItemHandle, HWND_TOP, Left + (Width div 2), Top + (Height div 2), 1, 1, SWP_NOACTIVATE);
    end;
  {$endif}
end;
 
procedure TWnd_Test.FormCreate(Sender: TObject);
var
  AppTitle: String;
begin
  {$ifdef mswindows}
    // das temporäre umsetzen des Application Titles wird gemacht um die Form eindeutig zu identifizieren, sollten mehrere Instanzen dieser Anwendung laufen.
    // Sichtbar für den Endnutzer ist das jedoch nicht.
    AppTitle := Application.Title;
    Application.Title := Application.ExeName;
    FTaskbarItemHandle := FindWindow(nil, LPCSTR(Application.Title));
    Application.Title := AppTitle;
  {$endif}
end;
Beim Verschieben des eigenen Fensters wird das ominöse Fenster in die Mitte des eigenen Fensters mit der Größe 1x1 gesetzt (0x0 geht nicht), ist aber dennoch nicht sichtbar und nicht aktiv (SWP_NOACTIVATE), damit die eigene Form nicht flackert. Das hier ist eine Art Notlösung für Leute die eine solche Funktion benötigen. Die IFDEFs habe ich gleich reingemacht damit man das ohne Änderung unter Windows und Linux nutzen kann. Dennoch sollte das mal überarbeitet werden, auch wenn es nur ein kleines Detail ist.

Edit: Die Größe ist nur noch 1x1 statt so groß wie das eigene Fenster, da sonst beim maximieren und wiederherstellen ein schwarzer Balken links neben der eigenen Form entstand.
Code: Alles auswählen
InitiateSystemShutdownExA(nil, nil, 0, true, false, $0005000F);
Have fun with this snippet ;)
compmgmt
 
Beiträge: 327
Registriert: 25. Nov 2015, 17:06
Wohnort: in der Nähe von Stuttgart
OS, Lazarus, FPC: Win 10 Pro | Lazarus 1.8.2 | FPC 3.0.4 | 
CPU-Target: i386 + x86_64
Nach oben

• Themenende •

Zurück zu Lazarus - Bugs



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast

porpoises-institution
accuracy-worried