my application is running in Background completely but shows it's activity via a notification icon in system tray. Now I wanted to add a popup-menu to that notification icon. Unfortunately I do not receive any events from it. That's what I'm doing currently to create the icon and its event handler:
First create an invisible window to use it's event handler
ZeroMemory(&wc,sizeof(WNDCLASSEX));
wc.cbSize=sizeof(WNDCLASSEX);
wc.lpfnWndProc=WndProc;
wc.hInstance=hInstance;
wc.lpszClassName=L"myCL";
RegisterClassEx(&wc);
hWnd=CreateWindowEx(WS_EX_CLIENTEDGE,L"myCL",L"myWN",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,
CW_USEDEFAULT,1,1,NULL,NULL,hInstance,NULL);
Next create and show the icon itself:
ZeroMemory(&niData,sizeof(NOTIFYICONDATA));
niData.cbSize=sizeof(NOTIFYICONDATA);
niData.uID=IDI_AAAA; // the icon's identifier
niData.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP;
niData.hIcon=(HICON)LoadImage(hInstance,MAKEINTRESOURCE(IDI_AAAA),IMAGE_ICON,
GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),
LR_DEFAULTCOLOR);
niData.hWnd=hWnd;
niData.uCallbackMessage=MY_TRAY_ICON_MESSAGE;
Shell_NotifyIcon(NIM_ADD,&niData);
And the event handler that is assigned to the invisible window and where I would have assumed the events from the icon should arrive too:
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case MY_TRAY_ICON_MESSAGE: // this should be related to notification icon but is never called
switch (lParam)
{
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_CONTEXTMENU:
break;
}
break;
default:
return DefWindowProc(hwnd,msg,wParam,lParam);
}
return 0;
}
Anybody an idea what is wrong here?
Related
I've written a code that dynamically creates a POPUP style window when the user clicks inside my main app window. Now I'd like the POPUP window to be automatically destroyed when the mouse cursor goes out of the POPUP wnd region. I know that i have probably handle the WM_MOUSEMOVE message but how to do that? Please provide a simple code for that if You can...
Use the WM_MOUSELEAVE message instead. However, note that this message has to be explicitly requested via TrackMouseEvent(), which your window can call when it receives its first WM_MOUSEMOVE message.
As #Remy Lebeau said, the following is the code implementation.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL Tracing = FALSE;
switch (message)
{
case WM_MOUSELEAVE:
{
DestroyWindow(hWnd);
break;
}
case WM_MOUSEMOVE:
{
if (!Tracing)
{
Tracing = TRUE;
TRACKMOUSEEVENT tme{};
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hWnd;
TrackMouseEvent(&tme);
}
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
you can compare the event.target and event.currentTarget, if both are same then you are out side of popup window else in side the popup window.
I am making an program and would like to have my program restarted when a person tries to resize the screen.
So far from searching the internet i've found that it's not possible to ''re-run your application'' as with code.
Everyone refers to just close and rerun it, but that's not what i want, i want the code to be doing that.
So i was thinking, can i not re-run winmain? and ' kill ' the current winmain instance in my code, but keep the ''shell (application?)'' active?
this is what i am trying to do:
LRESULT CALLBACK Proc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch (Message)
{
case WM_SIZE: //Check if the window has been resized
WinMain(this, this, this, NULL);
// or restart application code.
break;
case WM_PAINT: // we need to paint? lets paint!
if (DrawUI)
Render(true);
else
Render(false);
break;
case WM_CREATE:
return DwmExtendFrameIntoClientArea(hWnd, &pMargin); // extension of window frame into client area
break;
case WM_DESTROY:
PostQuitMessage(0); // We need to use this to exit a message loop
break;
default:
return DefWindowProc(hWnd, Message, wParam, lParam); // Making sure all messages are processed
break;
}
}
please see the code under WM_SIZE: that's what im trying to do, but i don't know how to do this correctly, and how to close the previous winmain.
I am trying to write a windowprocedure that would call the animation of a rectangle in the window only when the start button is clicked and stop when the stop button is clicked.
I tried doing this like this:
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_COMMAND:
switch (wParam)
{
case BUTTON_START:
stopClicked = false;
DestroyWindow(hStartButton);
CreateStopButton(hWnd);
Animate(hWnd);
return 0;
case BUTTON_STOP:
stopClicked = true;
DestroyWindow(hStopButton);
CreateStartButton(hWnd);
return 0;
}
case WM_CREATE:
AddMenus(hWnd);
CreateStartButton(hWnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProcW(hWnd, msg, wParam, lParam);
}
return 0;
}
the Animate function:
void Animate(HWND hWnd)
{
HDC hdcWnd = GetDC(hWnd);
while(!stopClicked)
{
//drawing code
}
ReleaseDC(hWnd, hdcWnd);
DeleteDC(hdcWnd);
}
The program crashes as it never exist the while(!stopClicked) loop.
My question is how to make that possible that the animation would stop on a button click?
Your application hanged, bucause you are waiting for a flag to change and there is no way it will change.
WindowProcedure is called on an event, and until you leave it, any other event won't be processed.
What you need to do is to perform steps of animation on timer.
You need to setup a timer which will send you an event which you have to handle and there you can draw next frame of your animation.
I use WM_MBUTTONDOWN to keep track of middle mouse button when it's pressed. So, when I click the middle mouse button at the mouse wheel, it will display the message on the console. I wonder why it doesn't work. Is WM_MBUTTONDOWN for another usage?
LRESULT CALLBACK UI::WindowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
// The message is post when we destroy the window.
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_MBUTTONDOWN:
cout << "Middle button clicked" << endl;
break;
// Default handling for other messages.
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Output:
Mouse used: Logitech
This looks like a driver issue. On some mice WM_MBUTTONDOWN message is not received. Make sure you use a mouse driver that supports middle button.
Check if the middle button works in other applications - if not, it is a driver issue.
I am trying to implement a chat window on a menu item click in the main window in win32. I have created a main window and am handling the chat window in the following way :
int CALLBACK TextChat::TextChatDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LPDRAWITEMSTRUCT pdis;
static HBRUSH hBrush;
static COLORREF GrayColor;
switch (uMsg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
}
break;
case WM_CLOSE:
EndDialog(hwndDlg, 1);
return true;
break;
case WM_INITDIALOG:
{
CentreWindow(hwndDlg);
ShowWindow(hwndDlg,SW_SHOW);
UpdateWindow(hwndDlg);
return TRUE;
}
}
return 0;
}
int TextChat::DoDialog()
{
//CreateWindowEx(
return DialogBoxParam(this->m_pApp->m_instance,MAKEINTRESOURCE(IDD_CHAT_DIALOG),
NULL, (DLGPROC) TextChatDlgProc, (LONG) this->m_pCC);
}
And from my main window on menu item clic, i am doing it the following way :
case WM_SYSCOMMAND:
{
switch (LOWORD(wParam))
{
case ID_TEXT_CHAT:
if(thisClass->m_pTextChat == NULL)
thisClass->m_pTextChat = new TextChat(thisClass->m_pApp,thisClass);
thisClass->m_pTextChat->DoDialog();
So i am using VS2008 and while debugging, the debugger goes inside TextChatDlgProc , but never goes inside WM_INITDIALOG and returns just like that. Hence, the chat window (resource IDD_CHAT_DIALOG) never get displayed. Any pointers towards resolving this problem is greatly appreciated. TIA
Regards,
grv
You say in a comment that the dialog has a rich edit control. That's the key!
You have to load the relevant library manually before these controls can be used. One of these:
LoadLibrary(TEXT("Msftedit.dll")); // for MSFTEDIT_CLASS
LoadLibrary(TEXT("Riched32.dll")); // for RICHEDIT_CLASS 3.2
LoadLibrary(TEXT("Riched20.dll")); // for RICHEDIT_CLASS 2.0
You can do that just once from WinMain().
Your TextChatDlgProc() needs to call DefWindowProc() for unhandled messages return FALSE for unhandled messages (default: switch case)