WINAPI/C++ wID abitrary number?

Home built / K9a2 cf-f
June 13, 2010 at 00:02:03
Specs: Windows XP, Athlon xp x2 64 5600 / 2gb
Basically I'm trying to finish something I started a
while ago, it's very simple but has been a bit of trouble....


All it is for is toggling the console close button from
enabled to disabled and visa-versa but I'm not sure if using
the window handle for wID is safe or recommended. It works but
I'm just not sure....

If it's not can anyone recommend a better way of doing this?

[compiled on] Mingw 3.14(Devpak) via Dev-c++ 4.9.9.2


#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <iostream>

int main(int argc, char *argv[])
{
    if (argc == 1)
    {
        return 1;
    }
    UINT revokeid = (unsigned int)GetConsoleWindow();
    MENUITEMINFO close;
    close.cbSize = sizeof(MENUITEMINFO);
    close.fMask = MIIM_STATE|MIIM_ID;
    close.fState = MFS_GRAYED;
    //Despite being wID msdn claims it's an UINT
    close.wID = revokeid;
    if (argv[1][0] == '1')
    {
         if (!SetMenuItemInfo(GetSystemMenu(GetConsoleWindow(), FALSE), SC_CLOSE, FALSE, &close))
         {
             std::cerr << "Failed API call" << std::endl;
             return 1;
         }
    } else {
        close.fState = MFS_ENABLED;
        close.wID = SC_CLOSE;
         if (!SetMenuItemInfo(GetSystemMenu(GetConsoleWindow(), FALSE), revokeid, FALSE, &close))
         {
             std::cerr << "Failed API call" << std::endl;
             return 1;
         }
    }
    DrawMenuBar(GetConsoleWindow());
    return 0;
}

BTW: This is not how I will be parsing the arguments,
that part is just to facilitate an independent example.


Thanks to anyone that has a look into it.


See More: WINAPI/C++ wID abitrary number?

Report •


#1
June 13, 2010 at 00:21:19
I forgot to mention that what I meant by the title is that *any* arbitrary number as wID does the trick so long as it doesn't overlap constants like "SC_CLOSE". If I pass back SC_CLOSE then the console can re-enable the menu on <alt>+<space> or icon click....

[edit]
MSDN links:

SetMenuItemInfo
MENUITEMINFO

Even it somebody could post a link to some useful info, because I can find any and the description is rather vague:

An application-defined value that identifies the menu item.
[/edit]


Report •

#2
June 13, 2010 at 13:35:20
Seems that any number < 0xf000 will do the trick without overlapping predefined values, I settled for 0x0fa0 because none the headers use that value for anything.

If anyone is interested in the program, here's a link: Swcde 2.2


Report •

#3
June 22, 2010 at 10:59:29
This topic's old, but I've been gone and now I'm back, so whatever.

I meant by the title is that *any* arbitrary number as wID does the trick so long as it doesn't overlap constants like "SC_CLOSE".
This is true. Your confusion is because you haven't run a Win32 message pump. Whatever you set wID to be, you'll have to watch for that ID in your message pump. (It comes across as the low word of wParam.)

A very quick and dirty example of what I'm talking about (Win32 app, from Dev-C++, no less):

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <cstdio>

const unsigned wID = 5; //Change this to see different output.

LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);

char szClassName[ ] = "Win32 Message Test";

int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance,
                   LPSTR lpszArgument, int show) {
    HWND hwnd;               
    MSG message;            

    WNDCLASSEX wincl;        
	wincl.cbSize = sizeof(WNDCLASSEX);
	wincl.cbClsExtra = 0;
	wincl.cbWndExtra = 0;

    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      

    wincl.style = CS_DBLCLKS;                
    wincl.hIcon = LoadIcon (0, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (0, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (0, IDC_ARROW);
    wincl.lpszMenuName = 0;
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    if (!RegisterClassEx (&wincl))
        return 0;

    hwnd = CreateWindowEx (0, szClassName, "Windows App", WS_OVERLAPPEDWINDOW,
	                       CW_USEDEFAULT,  CW_USEDEFAULT, 544, 375, 
						   HWND_DESKTOP, 0, hThisInstance, 0);
    
    //Add a new menu item
    char menuItemName[] = "Click Me";
    HMENU sysMenu = GetSystemMenu(hwnd, false);
    MENUITEMINFO item;
    item.cbSize = sizeof(item);
    item.fMask = MIIM_DATA|MIIM_FTYPE|MIIM_ID|MIIM_STATE|MIIM_STRING;
    item.fType = MFT_SEPARATOR;
    item.fState = MFS_ENABLED;
    item.wID = wID + 1;
	InsertMenuItem(sysMenu, SC_CLOSE, false, &item);
	
	item.fType = MFT_STRING;
	item.wID = wID;
    item.dwTypeData = menuItemName;
    item.cch = sizeof(menuItemName);
	if (!InsertMenuItem(sysMenu, wID + 1, false, &item)) {
		MessageBox(0, "InsertMenu #1 failed", 0, MB_OK|MB_ICONSTOP);
		return 1;
	}
	ShowWindow(hwnd, show);

    while (GetMessage(&message, 0, 0, 0)) {
        TranslateMessage(&message);
        DispatchMessage(&message);
    }
    return message.wParam;
}

//Called by the Windows function DispatchMessage()
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, 
                                  WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        case WM_SYSCOMMAND: //Because we added our item to the System Menu, 
			if (wParam == wID) { //and not our own menu.
				char str[44];
				std::sprintf(str, "The ID is: %d", wID);
				MessageBox(hwnd, str, "", MB_OK);
				break;
			} 
        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
    }
    return 0;
}


Report •

Related Solutions

#4
June 22, 2010 at 14:26:30
Thanks razor,

Nice clear example of a message pump, interestingly enough it would fault(window or console project on xp home sp3) until I commented out this line:

InsertMenuItem(sysMenu, SC_CLOSE, false, &item);


It's not strictly what I'm after, but I can learn a lot from it so it's helpful none the less.

All I was trying to do was disable and re-enable the console close button without screwing up the order or removing the bitmap.

Unless I changed wID right clicking on the title bar or <alt>+<space> would re-enable it when disabled. I was really just trying to affirm a safe value of wIDm not to to hook it or anything, just to ensure that it was properly disabled.


Thanks again!


Report •


Ask Question