I want to create dialog on windows that will be show on top level (even game window) like task manager. I wrote the next code:
static const wchar_t* className = L"GraphDialog";
WNDCLASSEX wx = {};
wx.cbSize = sizeof(WNDCLASSEX);
wx.hInstance = GetModuleHandle(NULL);
wx.lpszClassName = className;
if ( RegisterClassEx(&wx) )
{
HWND h = CreateWindowEx(WS_EX_TOPMOST, (LPCWSTR)className, NULL, WS_POPUP,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, NULL, NULL);
QWindow *qw = QWindow::fromWinId((WId)h);
if (qw)
{
GraphDialog* dialog = qobject_cast<GraphDialog*>(createWindowContainer(qw));
if (dialog)
{
dialog->init(...);
dialog->exec();
}
}
}
GraphDialog is QDialog.
Unfortunately I have mistake SIGSEGV when function CreateWindowEx is called.
Your registered class hasn't set the lpfnWndProc member which caused SIGSEGV.
You are passing NULL for lpWindowName:
HWND h = CreateWindowEx(WS_EX_TOPMOST, (LPCWSTR)className, NULL /*<------ lpWindowName*/, WS_POPUP,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, NULL /* <---- hInstance */, NULL);
I don't see any indication in the documentation that this is allowed. If it were, I'd also expect to see something documented for passing NULL to SetWindowText, but it is conspicuously absent.
It's also not clear that you're allowed to pass NULL in for the hInstance parameter.
Pass in some text for lpWindowName and have a look at passing in a handle for hInstance.
Related
I have tried tooltip feature in win32 code, when 'OK' clicked the message displays only when we hover on particular box. But the feature Iam expecting is auto display of message at particular box when 'OK' is clicked. Is it possible to add such feature of auto popup? I need some balloon type of error popup.
My exact scenario is to error popup when Zero is given as input in a dialog, when 'OK' is clicked.
HWND gzui_controls::create_tool_tip_balloon(HWND hdlg, int tool_id, PTSTR text) const { if (!tool_id || !hdlg || !text) { return FALSE; }
HWND hwndTool = GetDlgItem(hdlg, tool_id);
if (WM_LBUTTONUP)
{
HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
WS_POPUP | SWP_NOMOVE | TTS_NOPREFIX | TTS_BALLOON | BS_PUSHBUTTON,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hdlg, NULL,
getModuleInstance(), NULL);
if (!hwndTool || !hwndTip)
{
return (HWND)NULL;
}
// Associate the tooltip with the tool.
TOOLINFO toolInfo = { 0 };
toolInfo.cbSize = sizeof(toolInfo);
toolInfo.hwnd = hdlg;
toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
toolInfo.uId = (UINT_PTR)hwndTool;
toolInfo.lpszText = text;
SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
return hwndTip;
}
The following is an example of balloon tip for display information when input value is not valid.
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
// ...
editHwnd = CreateWindow(L"EDIT",
NULL,
WS_VISIBLE | WS_CHILD | ES_MULTILINE | WS_BORDER,
120,
10,
100,
100,
hWnd,
NULL,
hInst,
NULL);
// ...
case WM_COMMAND:
{
if (HIWORD(wParam) == EN_CHANGE)
{
// TODO: Add logic of detecting input value here
if (editHwnd == (HWND)lParam) // && inputVal == 0
{
balloonTip.cbStruct = sizeof(EDITBALLOONTIP);
balloonTip.pszText = L"Zero is given as input";
balloonTip.pszTitle = L"Tips";
balloonTip.ttiIcon = TTI_INFO;
Edit_ShowBalloonTip(editHwnd, &balloonTip);
}
}
}
break;
Refer to Edit Control, EDITBALLOONTIP structure, Edit_ShowBalloonTip macro
Note To use Edit_ShowBalloonTip macro, you must provide a manifest specifying
Comclt32.dll version 6.0.
It will like this:
I do this
HWND lParentWinHandle = GetForegroundWindow();
if (!CreateProcessA(NULL, lArgs, NULL, NULL, FALSE,
CREATE_NEW_CONSOLE, NULL, NULL,
&StartupInfo, &ProcessInfo))
{ ... }
// at this point a new window appears in the foreground.
HWND lChildWinHandle = GetForegroundWindow();
SetParent(lChildWinHandle , lParentWinHandle );
but lParentWinHandle and lChildWinHandle have the same value !
If you want to get the handle of the new process. You should use the process and thread handle of the PROCESS_INFO structure.
And according to the documentation you should wit with WaitForInputIdle until you start the search.
Code is similar to this (it is just a dirty sample no error checking):
BOOL CALLBACK EnumThreadWndProc(HWND hWnd, LPARAM lParam)
{
hWndMain = hWnd; // got the main window...
return FALSE; // ...stop enum
}
// ...
STARTUPINFO siStartInfo = {0};
PROCESS_INFORMATION piProcessInfo = {0};
CreateProcessA(NULL, pCmd,
NULL, NULL, FALSE, 0, NULL, NULL,
&siStartInfo,&piProcessInfo);
if(WaitForInputIdle(piProcessInfo.hProcess, 5000)==0)
{
EnumThreadWindows(piProcessInfo.dwThreadId,
EnumThreadWndProc, NULL);
}
else
{
// Could not start program
...
}
// ...
But please read Is it legal to have a cross-process parent/child or owner/owned window relationship?
I'm coding a application like Notepad in Win32 c++. But when i change szClassName in createWindow(), the menu can't work although it still show it when I run
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDC_NOTEPAD));
hWnd = CreateWindow(L"EDIT", szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, hMenu, hInstance, NULL);
//SetWindowLong(hWnd, GWL_WNDPROC, (LONG)WndProc);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
In CreateWindow(), the hMenu parameter is the control ID but not the menu handle.
I suggest creating the main window before adding a textbox:
WNDCLASSEX wc;
// ...
wc.lpszClassName="window class";
wc.lpszMenuName=hMenu;
// ...
RegisterWindowEx(&wc);
hWnd=CreateWindow("window class", ...);
// When processing WM_CREATE message in WndProc()
hEdit=CreateWindow("EDIT","your textbox", ... /* set hWndParent as hWnd */);
I think theForger's Win32 API Programming Tutorial is also a good place for you to start.
In a background process I want to display I short message like a balloon in the tray area. However, I do not want to add a tray icon just for that.
Hence I create a tooltip icon and want it to place near the tray.
However, sending TTM_UPDATETIPTEXT, TTM_TRACKPOSITION, TTM_TRACKACTIVATE returns 0. While I am not sure if this should be the case or not, the following code does not show the tooltip window and I don't know why:
This is the code:
// "hwnd" is the HWND to the hidden background window of my background process
HWND hTrayWnd = FindWindow(_T("Shell_TrayWnd"), NULL);
GetWindowRect(hTrayWnd, &trayPos);
HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_ALWAYSTIP | TTS_BALLOON,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hWnd, NULL, NULL, NULL);
LRESULT ret;
TOOLINFO toolInfo = { 0 };
ZeroMemory(&toolInfo, sizeof(toolInfo));
toolInfo.cbSize = sizeof(toolInfo);
toolInfo.hinst = GetModuleHandle(NULL);
toolInfo.lpszText = _T("Test Test");
toolInfo.hwnd = hWnd;
ret = SendMessage(hwndTip, TTM_SETTITLE, TTI_INFO , (LPARAM)_T("Test Title"));
This call returns zero:
ret = SendMessage(hwndTip, TTM_UPDATETIPTEXT, 0 , (LPARAM)&toolInfo); // needs hinst, lpszText, hwnd, cbSize
This call returns zero too:
ret = SendMessage(hwndTip, TTM_TRACKPOSITION, 0, MAKELPARAM(trayPos.left, trayPos.top));
ZeroMemory(&toolInfo, sizeof(toolInfo));
toolInfo.cbSize = sizeof(toolInfo);
toolInfo.hwnd = hWnd;
toolInfo.uId = 1;
And this too:
ret = SendMessage(hwndTip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&toolInfo); // needs hwnd, uId, cbSize
And the tooltip window is never shown.
I also tried to use TTM_ADDTOOL (as suggested in a comment) ad different order of my SendMessage calls but this too returns zero and no tooltip is shown:
LRESULT ret;
TOOLINFO toolInfo = { 0 };
ZeroMemory(&toolInfo, sizeof(toolInfo));
toolInfo.cbSize = sizeof(toolInfo);
toolInfo.lpszText = _T("Test Test");
toolInfo.hwnd = hWnd;
toolInfo.uId = 1;
toolInfo.rect.bottom = trayPos.bottom;
toolInfo.rect.left = trayPos.left;
toolInfo.rect.right = trayPos.right;
toolInfo.rect.top = trayPos.top;
//ret = SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
ret = SendMessage(hwndTip, TTM_SETTITLE, TTI_INFO , (LPARAM)_T("Test Title"));
//ret = SendMessage(hwndTip, TTM_UPDATETIPTEXT, 0 , (LPARAM)&toolInfo); // needs hinst, lpszText, hwnd, uId, cbSize
//ret = SendMessage(hwndTip, TTM_TRACKPOSITION, 0, MAKELPARAM(trayPos.left, trayPos.top));
//ret = SendMessage(hwndTip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&toolInfo); // needs hwnd, uId, cbSize
ret = SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
TTM_TRACKACTIVATE activates a 'tracking tooltip', which is created by setting TTF_TRACK in TOOLINFO::uFlags.
I am trying to make a small system tray program with only a context menu as its GUI.
However, I cannot get the tooltip to work. I properly setup NOTIFYICONDATA's szTip and everything else seems to work...what is preventing the tooltip from showing on mouseover?
void main()
{
int result;
hinst = GetModuleHandle( NULL );
memset( &wnd, 0, sizeof( wnd ) );
wnd.cbSize = sizeof( wnd );
wnd.lpszClassName = "MainWClass";
wnd.lpfnWndProc = MainWProc;
wnd.hInstance = hinst;
result = RegisterClassEx( &wnd );
hwnd = CreateWindowEx
(
0, //extended styles
wnd.lpszClassName, //class name
"Main Window", //window name
WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL | WS_MINIMIZEBOX, //style tags
CW_USEDEFAULT, //horizontal position
CW_USEDEFAULT, //vertical position
CW_USEDEFAULT, //width
CW_USEDEFAULT, //height
(HWND) NULL, //parent window
(HMENU) NULL, //class menu
(HINSTANCE) wnd.hInstance, //some HINSTANCE pointer
NULL //Create Window Data?
);
nid.cbSize = sizeof( nid );
nid.hWnd = hwnd;
nid.uID = 1;
nid.uVersion = NOTIFYICON_VERSION_4;
nid.uCallbackMessage = WM_CONTEXTMENU;
nid.hIcon = LoadIcon( hinst, MAKEINTRESOURCE( IDI_ICON1 ) );
strcpy( nid.szTip, "My Tooltip!" );
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
if( ! Shell_NotifyIcon( NIM_ADD, &nid ) )
{
printf("Shell_NotifyIcon( NIM_ADD, &nid ) failed.\r\n");
Sleep( INFINITE );
}
if( ! Shell_NotifyIcon( NIM_SETVERSION, &nid ) )
{
printf("Shell_NotifyIcon( NIM_SETVERSION, &nid ) failed.\r\n");
Sleep( INFINITE );
}
UpdateWindow( hwnd );
while( true )
{
//Dispatch for main window
if( PeekMessage( &msg, hwnd, NULL, NULL, PM_REMOVE ) )
{
DispatchMessage( &msg );
}
}
}
try adding the NIF_SHOWTIP flag, according to MSDN, NOTIFYICON_VERSION_4 requires that the tooltip be userdrawn.