WM_INITMENU has unexpected wParam for system menu - winapi

Message WM_INITMENU is supposed to contain menu handle in wParam. For some reason, for system menu, wParam is something different. Sometimes it is even negative number. However, it is always the same within the same instance.
I can ignore wParam and use the handle, returned by GetSystemMenu, to modify menu items - all works. I don't have other menus and can skip the check, but it is doesn't look accurate.
This is simple desktop C++ non-MFC project on Windows 10 21h1. I have a few other messages and all of them have expected wParam, so it must be "by design". Microsoft docs did not tell anything special. Maybe somebody knows, what is the value in wParam?
Thanks--

Related

How to Capture the Windows Message that is Sent from this Menu?

In most applications, when you click some MenuItem, a WindowsMessage is sent (usually WM_COMMAND), with a wParam representing the ID of the chosen MenuItem.
There is a certain program that has a Window Menu (the menu accessible via clicking the program's icon on the title-bar),
and I want to find what is the WindowsMessage that is sent when I choose a specific MenuItem from that Menu.
The program is soething you all know - the Command Prompt window, in Windows XP:
(cmd.exe)
And here is the Window Menu:
I want to capture the WindowsMessage and wParam for a MenuItem there,
for example the "Paste" MenuItem.
(but not just it.. any other might be as well)
Here is what I tried:
Method 1:
The first method I always try is to use Spy++.
The problem is that when I try to Log Messages for this specific program (the DOS window), Spy++ gives me this messagebox:
For some reason Spy++ won't capture WindowsMessages for this program.
So I went on to the second method that I use..
Method 2:
Resource Hacker (ResHacker.exe) is also good for finding the WindowsMessage that is sent from clicked MenuItems, and it does it quite easily.
If you run Resource Hacker, and then Open some EXE file with it,
you usually see these trees, which one of them is called "Menu",
and it contains all the details including the wParam:
The problem is, that when I try to use Resource Hacker on cmd.exe,
I get this:
As it can be seen, no "Menu" tree there.
My question:
Are there other ways, in addition to the 2 methods that I usually use,
that can be used to find the WindowsMessage (and wParam) that is sent for the "Paste" MenuItem in the Window Menu of the DOS window?
0xfff1 is the wParam, so in C# (you didn't specify the language you were using, but it should be easy enough to translate it):
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, uint lParam);
public const int WM_KEYDOWN = 0x01000;
void PasteInCommandPrompt(IntPtr hWnd)
{
SendMessage(handle, WM_COMMAND, 0xfff1, 0);
}
http://blogs.msdn.com/b/bill/archive/2012/06/09/programmatically-paste-clipboard-text-to-a-cmd-window-c-or-c.aspx
Edit: 22 September 2019
In the comments of Console window - programmatic command code (wParam of WM_COMMAND) (a question where a user was using the above link to Bill Lin's blog, but having trouble getting it working), #eryksun gave me the idea of looking for a ConvhostV2.dll.mui to find the all available menu commands. I couldn't find ConvhostV2.dll.mui...
But on my system I found C:\Windows\System32\en-US\ConhostV1.dll.mui, which when viewed with Resource Hacker (as #spaceman tried with cmd.exe), contains all the menu items available for cmd.exe.
The complete list of commands cmd.exe has are:
0xfff0: Copy
0xfff1: Paste
0xfff2: Mark
0xfff3: Scroll
0xfff4: Find
0xfff5: Select all
Besides paste (which allows you to execute arbitrary commands), select all and copy are very useful, as they let you get console output (albeit, stripping all virtual terminal sequences, the characters that specify text color).
If you are going deep into the route of manipulating command windows you may also be interested in the new "Windows Pseudo Console", which can let you have full control over cmd.exe, or any command line based application. See https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-console-conpty/ .

Creating a separate window against each click on push button

I am working on Windows GUI Application.There are 20 Push Buttons on my Window. Against each button click, I want to open up a new window for displaying some information. It can be anything which can display some information but since I am new to all this and I didn’t want to try anything complicated, I decided to go with the idea of creating a pop up window against each button click.
Now the problem that I am facing is that since there are 20 different windows, do I need to create 20 different window callback functions? Though there is only one control in the pop up window i.e. a Close sign, but even for that I need to have a CALLBACK function.
I had been trying with this but now this idea looks senseless. Is there any other option in which I can achieve the desired functionality?
Waiting for help.
If all of the windows should behave the same way, then you can create a single window procedure (what you're calling the CALLBACK function) that is shared by all of the pop-up windows.
Window procedures do not have to be unique to individual windows, but if multiple windows share the same window procedure, they will react identically to all messages that they receive.
For example:
// Message procedure for all pop-up windows.
LRESULT CALLBACK MyPopupWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
// handle any messages you want here in order to
// customize the behavior of your pop-up window
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
You specify a pointer to the MyPopupWndProc function when you register the window class for your pop-up windows (using the RegisterClassEx function), and then you pass the name of the registered window class when you call CreateWindowEx to create/display a pop-up window whenever one of the buttons on your main window is clicked.
Of course, if you're just wanting something simple for testing purposes, remember that you can always call the MessageBox function! No window procedures or class registration required.

Sending WM_HSCROLL to other program

Im trying to scroll other program (PowerPoint 2013) by sending WM_HSCROLL,
and it will work only if I offer the correct LPARAM (not NULL) to SendMessage.
The value of LPARAM is dynamic, it will change if you close and open a new program.
Now I can only get its value by hooking WM_HSCROLL and clicking scroll bar manually.
// This is my code:
LPARAM lParam = 0x0a616c38; // Found by hooking WM_HSCROLL
SendMessage(hTarget, WM_HSCROLL, SB_LINERIGHT, lParam);
So is it possible to get the correct LPARAM programatically?
Many thanks!
p.s. The scroll bar is not a real window in PowerPoint 2013.
p.s. It returns 1 if I use GetScrollInfo(hTarget, SB_CTL, &scrollinfo), but all values inside scrollinfo are zero.
p.s. Office Home and Student 2013 Official Site
Did you try to call GetLastError?
GetScrollInfo will probably not work across process boundaries, so I would say that's why you're not getting valid values back.
The lParam value of a WM_HSCROLL message is either NULL for the standard window scroll bar, or the handle of the scroll control. The handle of the scroll control will obviously change every time the program is run, so you need to find that out yourself before you can reliably simulate scroll input.
To do this, you can use the FindWindowEx function to search the parent window (hTarget in your example) for child windows of class "SCROLLBAR". As you will probably find more than one scrollbar child window you'll need some way to tell them apart - most probably, via the window's GWL_ID value as this will probably not change from run to run.

MFC - MDI main frame title is truncated when maximized child window has very long title

I have an MFC application using MDI, something similar to the MFC Scribble example/tutorial. When the child window is maximized, the caption/title of the main frame window is automatically adjusted so that the title of the child window is appended, like "Scribble - [Scribb1]". When the title of the child window is very long, it is truncated. The length of whole caption seems to be limited to about 160 characters. Is there a way to increase this limit and show more characters? I guess overriding WM_NCPAINT to redraw the caption is one way, but prefer other simple solution if there is one. I've tried overriding OnUpdateFrameTitle() and it doesn't seem to work for the whole combined caption.
Overriding OnUpdateFrameTitle and calling own implementation of the UpdateFrameTitleForDocument won’t work. Amit already tried your solution before even posting.
This is not even implemented by MFC. MDI window is not introduced by MFC. MDI frame window existed since I remember as part of the Windows OS.
Default MFC implementation down in the bowels of the MFC calls special MDI window procedure defined as DefFrameProc, as required.
Windows implementation for some mysterious reason truncate window text (displayed on the title bar of the MDI frame) to 160 characters, including terminating 0 when processing WM_SETTEXT message. This is probably the remnant of the old computers that did not have much memory to waste and all buffers sizes were kept to a minimum.
This is probably the remnant of the old computers that did not have much memory to waste and all buffers sizes were kept to a minimum and file names were 8.3 total 12 characters.
To fulfill your requirements and display full text you would have to make some changes.
Fortunately, I found really easy way of changing this behavior, in agreement with my MEMC requirement.
In your main frame class override DefWindowProcand change the code as follows:
LRESULT CMainFrame::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if(WM_SETTEXT == message)
{
// if set text (called from UpdateFrameTitleForDocument)
// do not call DefWindowProc
return CWnd::DefWindowProc(message, wParam, lParam);
}
// otherwise call DefWindowProc that in turn calls DefFrameProc
return CMDIFrameWndEx::DefWindowProc(message, wParam, lParam);
}
Now build and run.
This works for classinc and Visual studio styles of the MFC app.
Have a look at CFrameWnd::OnUpdateFrameTitle which internally is calling CFrameWnd::UpdateFrameTitleForDocument() method. It does the magic. It is a virtual method. You can override OnUpdateFrameTitle in your CMainFrm class and set the window title as desired.
If you did not know, MFC library is provided totally with the source. The CFrameWnd source is in winfrm.cpp (search for this file, and you will learn where the source for MFC on your PC)

WM_SIZE with loword==hiword==-1?

Just tried some small graphics application of mine on Windows 7, and I'm getting a WM_SIZE event with loword==hiword== -1 -- can this be safely ignored, or does it have some special meaning? I never saw such sizes on XP/Vista, only with Windows 7. The docs don't tell much about what hiword/loword can be, so I wonder if -1 has some special meaning. (Should I check for negative in general, or is -1 the only case?)
what is in the wParam ? the lParam should contain the size of the client area of the window, but the wParam shows what type of resizing happened: minimized, maximized, ...
i seem to remember that, if the window is minimized, the client area has no size, thus the strange values in WM_SIZE. idem for values returned by GetWindowPos() or GetWindowPlacement().

Resources