Software Archive
Read-only legacy content
17061 Discussions

Display drop-down menu from within program

isn-removed200637
1,058 Views
What message can I send to a window from within the program
to display a drop-down menu
as if I had selected an item from the menu bar using the mouse or a hot-key?
TIA
0 Kudos
9 Replies
Jugoslav_Dujic
Valued Contributor II
1,058 Views
There are two ways; the one you seem to be looking for (simulating user input) can be achieved using Win32 APIs keybd_event, mouse_event or SendInput. Another, pure "programatic" would be to use TrackPopupMenu, GetMenuItemRect and GetMenuItemInfo.

Jugoslav
0 Kudos
isn-removed200637
1,058 Views
Sorry, for 'in DFWINTY' ead 'in DFWIN'. Meanwhile, I checked and GetMenuItemRect is in USER32.dll
0 Kudos
isn-removed200637
1,058 Views
Thanks. I have changed the function call to GetMenuItemRect(hWnd, hMenu , hItem, LOC(menrect), but what should the Interface block contain? At the moment I have the following:
 
	interface 
	logical(4) function  GetMenuItemRect(hWnd, hMenu , hItem, menrect)  
!DEC$ IF DEFINED(_X86_) 
!DEC$ ATTRIBUTES STDCALL, ALIAS : '_GetMenuItemRect@16' :: GetMenuItemRect 
!DEC$ ELSE 
!DEC$ ATTRIBUTES STDCALL, ALIAS :  'GetMenuItemRect'   :: GetMenuItemRect 
!DEC$ ENDIF 
	use dfwinty 
	integer hWnd 
	integer hMenu 
	integer hitem 
	type(T_RECT) menrect 
	end function GetMenuItemRect 
	end interface 

Where should the !DEC$ATTRIBUTES REFERENCE:: menRect. go?


I still get unsatisfied external reference when I compile and link.
GetMenuItemRect is in USER32.dll (which is referenced by USER32.LIB)
and that library is included in my link list.


BTW, my last two posts to this thread have got lost, even though I got an e-mail
confirmation of each being accepted. There were some annoying problems with the message
board software on Tuesday which probably caused this.

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,058 Views
!DEC$ATTRIBUTES REFERENCE should go anywhere within interface block.
(preferrably next to TYPE(menRect):: Rect). See ...DFIncludeDFWIN.f90 for samples on how various argument combinations are translated. I believe link error is just a consequence of that.

Jugoslav
0 Kudos
isn-removed200637
1,058 Views
Thanks Jugoslav.

I found the following works: the linker finds the routine _getmenuitemrect@16. Note that I removed STDCALL from the first !DEC$ATTRIBUTES compiler directive, which I think otherwise adds a(nother?) leading underline to the alias:

 
	interface 
	logical(4) function  GetMenuItemRect(hWnd, hMenu , hItem, menrect)  
!DEC$ IF DEFINED(_X86_) 
!DEC$ ATTRIBUTES ALIAS : '_GetMenuItemRect@16' :: GetMenuItemRect 
!DEC$ ATTRIBUTES REFERENCE :: menrect 
!DEC$ ELSE 
!DEC$ ATTRIBUTES STDCALL, ALIAS :  'GetMenuItemRect'   :: GetMenuItemRect 
!DEC$ ATTRIBUTES REFERENCE :: menrect 
!DEC$ ENDIF 
	use dfwinty 
	integer hWnd 
	integer hMenu 
	integer hitem 
	type (T_RECT) menrect 
C	integer menrect 
	end function GetMenuItemRect 
	end interface 
C FLAGS REQUIRED BY TRACKPOPUPMENU (Taken from WINUSER.H) 
C THAT ARE NOT IN DFWINTY.F90 
	integer, parameter:: TPM_TOPALIGN        =#0000 
	integer, parameter:: TPM_VCENTERALIGN    =#0010 
	integer, parameter:: TPM_BOTTOMALIGN     =#0020 
	integer, parameter:: TPM_HORIZONTAL      =#0000      
	integer, parameter:: TPM_VERTICAL        =#0040      
	integer, parameter:: TPM_NONOTIFY        =#0080      
	integer, parameter:: TPM_RETURNCMD       =#0100

However, when I call GETMENUITEMRECT, it returns zero (and the RECT structure menrect contains all zeros) and GETLASTERROR gives error code = 1400, which
shows that it failed because of an invalid window handle. I do not understand this, because I used the same window handle as I used to get the handle to the pop-up menu that I display. I even tried using the handle returned by GETACTIVEWINDOW(), but with the same failure.


TRACKPOPUPMENU works ok though and I can display the drop-down menu that I want, but I cannot display it in its usual relationship to the window's menu because of the failure to get the co-ordinates for the menuitem which normally activates the drop-down menu. Sigh.

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,058 Views
hWnd should be the handle of frame window (or the window that contains the main menu). However, I find very odd that the interface block without STDCALL works. I tried it on my 5.0D, and your first version with only REFERENCE added works fine. The way you declared it now hWnd, hMenu and iItem arguments will be passed by reference instead of by value and you'll surely get an error like that (the linking will pass fine, but the API will get wrong numbers at run-time). (STDCALL attribute introduces call-by-value as default).

Jugoslav
0 Kudos
isn-removed200637
1,058 Views
OK jugoslav, I get the point..so I went back to this...
 
	interface 
	logical(4) function  GetMenuItemRect(hWnd, hMenu , hItem, menrect)  
cDEC$ ATTRIBUTES STDCALL, ALIAS : '_GetMenuItemRect@16' :: GetMenuItemRect 
cDEC$ ATTRIBUTES REFERENCE :: menrect 
	use dfwinty 
	integer hWnd 
	integer hMenu 
	integer hitem 
	type (T_RECT) menrect 
	end function GetMenuItemRect 
	end interface 

and used the following call


RETLOG=GetMenuItemRect(ghWnd,hMenu,2, dropdrect )< p>
The routine compiled ok (with dropdrect defined as TYPE (T_RECT) ), but I am still getting the link error

 
OPENFILE.OBJ : error LNK2001: unresolved external symbol _GETMENUITEMRECT@16 
Release/generic.exe : fatal error LNK1120: 1 unresolved externals 

With the above interface block, the alias '_GetMenuItemRect@16' should ensure that the required routine is recognised. I know that TrackPopUpMenu has exactly similar interface(but with 7 arguments, hence @28 is appended to the alias '_TrackPopUpMenu' ) and it is found and linked ok and I know that both routines are
in USER32.DLL. It is frustrating that the linker is still refusing to find GetMenuItemRect !!
I give up!
regards
tony richards

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,058 Views
Heck, Tony, I've got a feeling that you're doing something terribly wrong, but I can't figure out what. The linker error suggests that the caller doesn't see ALIAS.
Where are you trying to put that INTERFACE in? If in ...DFWIN.f90, that won't work, because it's dfwin.mod file that matters, and it's not recompiled. You should put it in your calling code. Alternatively, you could also edit and recompile dfwin.f90, but you should copy dfwin.mod to ...DFInclude. (But I don't recommend that, since I did it once and had pains when upgrading and moving code to other machines).

If I'm wrong, I guess I'll give up too :-).
0 Kudos
Steven_L_Intel1
Employee
1,058 Views
See my reply regarding the interface block.

Steve
0 Kudos
Reply