TForm Systemmenu MenuItem deaktivieren

Rund um die LCL und andere Komponenten
Antworten
TBug
Beiträge: 179
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

TForm Systemmenu MenuItem deaktivieren

Beitrag von TBug »

Und schon das nächste Problem.

Wie kann man unter Lazarus zum Beispiel das MenuItem "Verschieben" des Systemmenus einer Form deaktivieren?

Unter Delphi geht das problemlos mit "EnableMenuItem()".


.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: TForm Systemmenu MenuItem deaktivieren

Beitrag von Michl »

Code: Alles auswählen

uses Windows, ...
...
procedure TForm1.FormCreate(Sender: TObject);
var
  mnu: HMENU;
  info: MENUITEMINFO;
  s: String;
begin
  mnu := Getsystemmenu(Handle, false);
 
//  EnableMenuItem(mnu, SC_MOVE, MF_BYCOMMAND or MF_GRAYED);
//  DeleteMenu(mnu, SC_MOVE, MF_BYCOMMAND);
 
  s := 'Cannot move';
  info.fMask := MIIM_TYPE;
  info.dwTypeData := PChar(s);
  GetMenuItemInfo(mnu, SC_MOVE, false, info);
  ModifyMenu(mnu, SC_MOVE, MF_BYCOMMAND or MF_GRAYED, 0, info.dwTypeData);
end; 
Windows only!!!

Komischerweise funktioniert nur DeleteMenu und ModifyMenu und nicht EnableMenuItem. Das ist aber scheinbar nicht nur hier so: http://stackoverflow.com/questions/2602 ... -menu-item

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

TBug
Beiträge: 179
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: TForm Systemmenu MenuItem deaktivieren

Beitrag von TBug »

Code: Alles auswählen

 ModifyMenu(mnu, SC_MOVE, MF_BYCOMMAND OR MF_GRAYED, 0, info.dwTypeData);
Das ist nicht die Lösung, da das MenuItem durch die Verwendung von 0 als 4. Parameter beim Disable'n nicht mehr "enabled" gemacht werden kann.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: TForm Systemmenu MenuItem deaktivieren

Beitrag von Michl »

Ja geht nicht. K.A. was da bei Windows schief läuft.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

TBug
Beiträge: 179
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: TForm Systemmenu MenuItem deaktivieren

Beitrag von TBug »

Michl hat geschrieben:Ja geht nicht. K.A. was da bei Windows schief läuft.
Ich glaube nicht an ein Windows-Problem denn unter Delphi2007 funktioniert folgender Code ja problemlos.

Code: Alles auswählen

 
procedure THGFormPanel.SetBorderIconsState();
var
  lSysMenu: HMENU;
begin
  lSysMenu := GetSystemMenu(Handle, False);
 
  if (FMoveable) then
   begin
    //ModifyMenu(lSysMenu, SC_MOVE, MF_BYCOMMAND or MF_ENABLED, SC_MOVE, 'An');
    EnableMenuItem(lSysMenu,SC_MOVE, MF_BYCOMMAND or MF_ENABLED);
   end
  else
   begin
    //ModifyMenu(lSysMenu, SC_MOVE, MF_BYCOMMAND or MF_GRAYED, SC_MOVE, 'Aus');
    EnableMenuItem(lSysMenu,SC_MOVE, MF_BYCOMMAND or MF_GRAYED);
   end;
  DrawMenuBar(Handle);
end;
 
Auch die auskommentierten Zeilen mit ModifyMenu() funktionieren.


.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: TForm Systemmenu MenuItem deaktivieren

Beitrag von Michl »

TBug hat geschrieben:Ich glaube nicht an ein Windows-Problem denn unter Delphi2007 funktioniert folgender Code ja problemlos.
wenn man eine Suchmaschine anwirft, kommen da die Meldungen von unterschiedlichsten Programmiersprachen. Ich glaube daher nicht an ein Problem von Lazarus (evtl. hat Delphi bei den Methoden noch etwas davor/danach zugeschaltet???).

Wenn man mal in die Definition schaut (da wo sich ein Fehler verstecken könnte):

Code: Alles auswählen

//func.inc
...
function EnableMenuItem(hMenu:HMENU; uIDEnableItem:UINT; uEnable:UINT):WINBOOL; external 'user32' name 'EnableMenuItem';    
entspricht diese genau der Definition: https://msdn.microsoft.com/en-us/librar ... 85%29.aspx

Ich habe nicht intensivst nach der Lösung dafür gesucht (habe sowas auch noch nie benötigt) und kann dir leider nicht sagen, was Delphi da anders macht.

Alternativ genügt es dir ja evtl., bei ausgeschaltetem "Verschieben" dieses MenuItem zu entfernen (RemoveMenu und InsertMenu funktionieren bei mir problemlos)?!

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: TForm Systemmenu MenuItem deaktivieren

Beitrag von Michl »

Habe jetzt doch noch mal probiert und eine Alternative, wie es wie von dir gewünscht ist, gefunden (kann man sicherlich noch verkürzen):

Code: Alles auswählen

procedure TForm1.CheckBox1Change(Sender: TObject);
var
  FMoveCaption: String;
  FMenuMove: HMENU;
  FInfo: MENUITEMINFO;
begin
  if CheckBox1.Checked then
    FMenuMove := Getsystemmenu(Handle, true)
  else begin
    FMenuMove := Getsystemmenu(Handle, false);
    GetMenuString(FMenuMove, SC_MOVE, PChar(FMoveCaption), MAX_PATH, MF_BYCOMMAND);
    FInfo.fMask := MIIM_TYPE;
    FInfo.dwTypeData := PChar(FMoveCaption);
    GetMenuItemInfo(FMenuMove, SC_MOVE, false, FInfo);
    ModifyMenu(FMenuMove, SC_MOVE, MF_GRAYED, 0, FInfo.dwTypeData);
  end;
end; 
Siehe: https://msdn.microsoft.com/en-us/librar ... 85%29.aspx
Zitat: "bRevert ... The action to be taken. If this parameter is FALSE, GetSystemMenu returns a handle to the copy of the window menu currently in use. The copy is initially identical to the window menu, but it can be modified. If this parameter is TRUE, GetSystemMenu resets the window menu back to the default state. The previous window menu, if any, is destroyed."

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

TBug
Beiträge: 179
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: TForm Systemmenu MenuItem deaktivieren

Beitrag von TBug »

Die Idee mit GetMenuString war Gold wert, da es ja wesentlich einfacher ist, als den String über GetMenuItemInfo auszulesen.

Obwohl ich aufgrund der Umständlichkeit dieses Konstrukt dennoch ersteinmal als Provesorium sehe.

Wenn man allerdings wie es eigentlich von Windows erwartet wird ".cbSize" setzt, dann funktioniert das nicht mit MIIM_TYPE im ".fMask" sondern nur mit MIIM_FTYPE.

Code: Alles auswählen

 
  lItemInfo.cbSize := SizeOf(MENUITEMINFO);
  lItemInfo.fMask := MIIM_FTYPE;
  lItemInfo.dwTypeData := PChar(lItemCaption);
 
Es funktioniert so wie es gewünscht ist und der Feinschliff kann auch noch später erfolgen, wenn einmal alle Komponenten umgestellt sind, so dass sie ersteinmal funktionieren.

Danke nochmals.


.

Antworten