Tommi Prami 131 Posted January 22, 2019 (edited) I would need to get position of MenuItem, of top level TMenuItem, so always visible.  I would like to show balloonhint on top of that, to tell user that, you should go in this menu, to process stuff, pretty much now, if suints your timetable 😉  -Tee- Edited January 22, 2019 by Tommi Prami Share this post Link to post
Guest Posted January 22, 2019 (edited) GetMenuBarInfo API should help. Â I have no Delphi at hand at the moment but the following quick test works in Lazarus: function GetWindowMenuItemRect(Handle: THandle; Index: Integer): TRect; var Info: MENUBARINFO; begin FillChar(Info, SizeOf(Info), 0); Info.cbSize := SizeOf(Info); Win32Check(GetMenuBarInfo(Handle, $FFFFFFFD, Index, @Info)); Result := Info.rcBar; end; function GetScreenCanvas: TCanvas; begin Result := TCanvas.Create; try Result.Handle := GetDC(0); Result.Pen.Style := psSolid; Result.Pen.Color := clRed; Result.Brush.Style := bsClear; except Result.Free; raise; end; end; procedure TForm1.Button1Click(Sender: TObject); var C: TCanvas; I: Integer; begin C := GetScreenCanvas; try for I := 0 to MainMenu1.Items.Count - 1 do C.Rectangle(GetWindowMenuItemRect(Handle, I + 1)); finally C.Free; end; end; Â Edited January 22, 2019 by Guest Share this post Link to post
Tommi Prami 131 Posted January 22, 2019 Thanks man, I'll check... Gort to make couple of changes to make it compile, weirdly it did not allow me to assign Returned rect to result. Type in Delphi seems to be TMenuBarInfom and last parameter of GetMenuBarInfo is defined as Var-parameter. So I think I'll have to pass the whole record, not just pointer.   function GetWindowMenuItemRect(const AHandle: THandle; const AIndex: Integer): TRect; var  LMenuBarInfo: TMenuBarInfo; begin  FillChar(LMenuBarInfo, SizeOf(LMenuBarInfo), 0);  LMenuBarInfo.cbSize := SizeOf(LMenuBarInfo);  {$WARN SYMBOL_PLATFORM OFF}  Win32Check(GetMenuBarInfo(AHandle, Integer($FFFFFFFD), AIndex, LMenuBarInfo));  {$WARN SYMBOL_PLATFORM ON}  Result.Top := LMenuBarInfo.rcBar.Top;  Result.Left := LMenuBarInfo.rcBar.Left;  Result.Height := LMenuBarInfo.rcBar.Height;  Result.Width := LMenuBarInfo.rcBar.Width; end;  It just gives me System Error.  Code: 1400. Invalid window handle  Tried to pass Windows Handle, MenuITems handle, did not Accept it... 😞 Weird.  -Tee- Share this post Link to post
Tommi Prami 131 Posted January 22, 2019 Tried all combinations of different handles and indexes, I could think of... Damnation. Now have to go tortured by the Dentist, and not event the Delphi-coding one 😞 Share this post Link to post
Guest Posted January 22, 2019 (edited) Your fix looks fine to me. Apart from the var parameter declaration the rest should be the same. Pass it the form's Handle (like in my example, I'm passing it Self.Handle where Self is the instance of the form).  Good luck with the Dentist! 😉 Edited January 22, 2019 by Guest Share this post Link to post
Guest Posted January 22, 2019 (edited) I've checked it with Delphi XE. The declaration of TMenuBarInfo in Windows unit seems to be wrong (packed record, 29 bytes). Simply redeclare it in your unit:  type {$A8} // default quadword-alignment PMenuBarInfo = ^TMenuBarInfo; tagMENUBARINFO = record cbSize: DWORD; rcBar: TRect; hMenu: HMENU; hwndMenu: HWND; { fBarFocused:1: BOOL;} { bar, popup has the focus } { fFocused:1: BOOL; } { item has the focus } FocusedBits: BYTE; end; TMenuBarInfo = tagMENUBARINFO; function GetMenuBarInfo(hend: HWND; idObject, idItem: Longint; var pmbi: TMenuBarInfo): BOOL; stdcall; external user32 name 'GetMenuBarInfo';  which makes the record size 32 bytes, then it works:   BTW, it's already fixed in Rio.  Edited January 22, 2019 by Guest Share this post Link to post
Tommi Prami 131 Posted January 24, 2019 Thanks,  I see nothing wrong in that, but I just can't see why Compiler does not like it. It might be something trivial, but I just can't figure it out.  TMenuBarInfo = tagMENUBARINFO; // <- [dcc32 Error] : E2029 '=' expected but identifier 'TMenuBarInfo' found   Share this post Link to post
Guest Posted January 24, 2019 1 hour ago, Tommi Prami said: Thanks,  I see nothing wrong in that, but I just can't see why Compiler does not like it. It might be something trivial, but I just can't figure it out.  TMenuBarInfo = tagMENUBARINFO; // <- [dcc32 Error] : E2029 '=' expected but identifier 'TMenuBarInfo' found   Sorry, I've been vague. Here's the full code which works in Delphi XE, I hope it helps: GetWindowMenuItemRect example Cheers! Share this post Link to post
Tommi Prami 131 Posted January 24, 2019 (edited) Thanks,  Can't see any difference but if I copy record and external method declarations from github, it compiles. weirdest thing ever 😄 Edited January 24, 2019 by Tommi Prami Share this post Link to post
Guest Posted January 24, 2019 30 minutes ago, Tommi Prami said: Thanks,  Can't see any difference but if I copy record and external method declarations from github, it compiles. weirdest thing ever 😄 Just a thought... Sounds like the units in your uses clause are listed in a different order so the type declarations resolve differently. Share this post Link to post
Tommi Prami 131 Posted January 24, 2019 type  {$A8} // default quadword-alignment  PSTMenuBarInfo = ^TSTMenuBarInfo;  tagSTMENUBARINFO = record   cbSize: DWORD;   rcBar: TRect;   hMenu: HMENU;   hwndMenu: HWND;   { fBarFocused:1: BOOL;} { bar, popup has the focus }   { fFocused:1: BOOL; }  { item has the focus }   FocusedBits: BYTE;  end;  TSTMenuBarInfo = tagSTMENUBARINFO; function STGetMenuBarInfo(hend: HWND; idObject, idItem: Longint; var pmbi: TSTMenuBarInfo): BOOL;  stdcall; external user32 name 'GetMenuBarInfo'; function GetWindowMenuItemRect(const AHandle: THandle; const AIndex: Integer): TRect; var  LMenuBarInfo: TSTMenuBarInfo; begin  FillChar(LMenuBarInfo, SizeOf(TSTMenuBarInfo), 0);  LMenuBarInfo.cbSize := SizeOf(TSTMenuBarInfo);  {$RANGECHECKS OFF}  {$OVERFLOWCHECKS OFF}  {$WARN SYMBOL_PLATFORM OFF}  Win32Check(STGetMenuBarInfo(AHandle, Longint($FFFFFFFD), AIndex, LMenuBarInfo));  {$WARN SYMBOL_PLATFORM ON}  {$OVERFLOWCHECKS ON}  {$RANGECHECKS ON}  Result := LMenuBarInfo.rcBar; end; Changed types and method name to make sure it uses different types, added some far fetched compiler defines. Same code works using rest of your code. But failed on app that woulöd actually need to use it :). Have an idea tough... Gives me System Error.  Code: 1400. Invalid window handle  LEt me see...  btw... Thanks for help! Share this post Link to post
Tommi Prami 131 Posted January 24, 2019 Could this be messed up with visual form inheritance.  It works in clean demo app, basically your code, with those name changes I've made. Have to typecast the constant because otherwise I'll get an Constant violates subrange bounds error, but not even that matter/happen in a clean new App.  -Tee- Share this post Link to post