Separate taskbar button for dialog - c++

I am supporting a WinAPI/ATL based app with many dialog windows created depending on user actions. Most of the dialogs are unowned windows. If several dialogs are created at the same time, their taskbar buttons are grouped together on the Taskbar (default behavior).
Now I have a task to create a separate taskbar button for one of dialog windows. I can't find any relevant info on how to do this. I even tried to use the ITaskbarList COM interface, but its AddTab() method works like the default model above.
Is it possible to place more than one button on the Taskbar for one instance of the app? If yes, please explain how I can implement this.

On Windows 7 and later, you can assign a different Application User Model ID to the dialog and it will not be grouped with the other dialogs on the Taskbar.
See Raymond Chen's blog article about this topic:
How do I customize how my application windows are grouped in the Taskbar?
Also see:
Developing for the Windows 7 Taskbar — Application ID
For example:
int WINAPI wWinMain(HINSTANCE hinst, HINSTANCE hinstPrev,
LPWSTR lpCmdLine, int nShowCmd)
{
SetCurrentProcessExplicitAppUserModelID(L"MyCompany.MyApp.MainProcess");
...
HWND hDlg = ...
IPropertyStore *pps = NULL;
if (SUCCEEDED(SHGetPropertyStoreForWindow(hDlg, IID_PPV_ARGS(&pps))))
{
PROPVARIANT pv;
PropVariantInit(&pv);
InitPropVariantFromString(L"MyCompany.MyApp.LoneDialog", &pv);
pps->SetValue(PKEY_AppUserModel_ID, pv);
PropVariantClear(&pv);
pps->Release();
}
...
return 0;
}

Related

Windows Dialog Box not getting opened

Im trying to open a Dialog box in Windows machine(using windows credential provider), when the user presses a button. i tried the below code but, dialog box is not getting opened. i have a resource "IDD_DIALOG1" and callback method "ChangePasswordProc".
HWND hwndOwner = nullptr;
::DialogBox(HINST_THISDLL, MAKEINTRESOURCE(IDD_DIALOG1), hwndOwner,ChangePasswordProc);
I didn't write in Windows GUI for a looong time, but perhaps try something like this:
HWND dialog = ::DialogBox(HINST_THISDLL, MAKEINTRESOURCE(IDD_DIALOG1), hwndOwner,ChangePasswordProc);
ShowWindow(dialog, SW_SHOW);
I remember, that creating window does not imply showing it - it must be done explicitly.
To create any window from inside of Credential Provider you must first get parent window handle by calling OnCreatingWindow method of ICredentialProviderCredentialEvents interface.
HRESULT OnCreatingWindow([out] HWND* phwndOwner);
Pointer to this interface is supplying to your provider by calling Advise method of its ICredentialProviderCredential interface :
HRESULT Advise([in] ICredentialProviderCredentialEvents* pcpce);
Have a look at this post.

Make focused modeless dialog topmost

So I have my main dialog that calls modeless dialogs through this function (this is the legacy code on the project):
void MyClass::ShowDialog(CDialog* dialog)
{
if (!IsWindow(dialog->m_hWnd))
{
return;
}
int nCmdshow1 = dialog->IsWindowVisible() ? SW_HIDE : SW_SHOW;
dialog->ShowWindow( nCmdshow1 );
}
Problem: all sub dialogs stay on top of my main dialog.
Desired behavior: whichever's focused (they are all modeless), be it the main dialog, or sub dialogs, I want it to be the topmost dialog. Thank you!
Note: I already tried on my main dialog's OnInitDialog() these but didn't work:
1. SetWindowPos(&this->wndTop,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
2.SetWindowPos(&this->wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
EDIT
Also, sub dialogs are created this way:
m_subDlg1->Create( SubDlg1::IDD, this );
As long as there is an owner relation between two windows. the owner of a window can never be on top of the owned window.
Windows in an owner, parent, child relation always behave the same. The owned/child window is always on top of the parent/owner.
If you want to break this, you have to break the owner/child relation. Let all dialog windows have no owner... than they may float freely.
But: I will expect the you program doesn't behave better. Even worse. User might search windows that are deep below covered under other windows. And they will never get in front, when your program gets active.
See the description about parent/child/owned windows here. Also this article might be helpful.
Edit: The problem is that internally the MFC sets the main window as an owner if no parent is given. Only the call to BOOL Wnd::CreateDlgIndirect(LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd, HINSTANCE hInst) allows to leave pParentWnd NULL.
So you may create the window as normal, but use SetParent(NULL) after it was created. Again the MFC ASSERTs this. SO you may use the API function and the handle of your dialog.

Programmatically hide an application on windows

Is there a way to programmatically hide an application on windows? I want to achieve the same thing as the windows+D shortcut, but for a single application. I want to do this from within that application (application consists of several windows, one of those can't be moved, resized, closed or minimized by the user). Application is written in c++ and uses Qt for the UI.
to do so it's so easy:
1- retrieve the handle to that window:
HWND hChild = GetDlgItem(hWnd, ID_MYCHILD);
2- send to it SW_SHOW either using ShowWindow or via SendMessage:
ShowWindow(hChild, SW_HIDE); // hide
ShowWindow(hChild, SW_SHOW); // show
SendMessage(hChild, SW_HIDE, 0, 0); // hide
SendMessage(hChild, SW_SHOW, 0, 0); // show
if the window doesn't belong to your application then:
1 - retrieve the main window with:
HWND hWnd = GetForegroundWindow(void);
2- use the above to hide/show it
ShowWindow(HwndWindow, SW_MINIMIZE);
Here's the MSDN ShowWindow documentation.
In addition you may find EnumChildWindows useful for finding all these windows if their handles aren't readily available to you.

how to make a clickable button in c++ win32

anyone can tell me how to use a bitmap as a button, actually i can create a static control and could set a picture to it but the thing is that i don't know how to use it as a button, i am using c++ win32.
This is how i create the bitmap
Code:
HWND Profile_Stuff(HWND hWnd, HINSTANCE hInst)
{
HWND Profile_Pic;
Profile_Pic = CreateWindow("STATIC", NULL, SS_BITMAP|WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_BORDER, 5,5,33,33, hWnd, NULL, hInst, NULL);
HBITMAP hBmp = (HBITMAP)LoadImage(NULL, "camera1.jpg", IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
if(hBmp == NULL){
MessageBox(NULL, "Error while loading image", "Error", MB_OK|MB_ICONERROR);
}
SendMessage(Profile_Pic, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBmp);
return 0;
}
then i call the function in main window wm_create message handler which creates it successfully, now i don't know to use it as a button, like we have a picture of an advertisement at the bottom of bit torrent application.
i am using visual studio c++ with win32 api.
If you want a button control, you should create a button control. The visual representation can be controlled by the application. To do so, specify the BS_OWNERDRAW Button Style. A button control with this style sends a WM_DRAWITEM message to the control parent whenever a visual aspect has changed. The control parent can then render the control as it sees fit.
An introduction to owner-drawn controls is available at Custom Controls. If you wish to retain some parts of the button control (e.g. its border), see Using Visual Styles with Custom and Owner-Drawn Controls for details (or DrawFrameControl if you aren't using Visual Styles).
Fully working sample code for an owner-drawn button control can be found in this answer.
In Windows, the windows belong to a class, a the class defines the windows procedure for all windows of that class, meaning how they react to events.
If you create a STATIC window, it will not react to any click and will not be useable as a button.
You could create a custom class, register it along with a custom windows procedure able to mimic a BUTTON. But unless you have very special requirements just create an owner drawn button as shown in #IInspectable's answer

Do you have to register a Dialog Box?

So, I am a total beginner in any kind of Windows related programming. I have been playing around with the Windows API and came across a couple of examples on how to initialize create windows and such.
One example creates a regular window (I abbreviated some of the code):
int WINAPI WinMain( [...] )
{
[...]
// Windows Class setup
wndClass.cbSize = sizeof( wndClass );
wndClass.style = CS_HREDRAW | CS_VREDRAW;
[...]
// Register class
RegisterClassEx( &wndClass );
// Create window
hWnd = CreateWindow( szAppName, "Win32 App",
WS_OVERLAPPEDWINDOW,
0, 0, 512, 384,
NULL, NULL, hInstance, NULL );
[...]
}
The second example creates a dialog box (no abbreviations except the WinMain arguments):
int WINAPI WinMain( [...] )
{
// Create dialog box
DialogBox(hInstance,
MAKEINTRESOURCE(IDD_MAIN_DLG),
NULL,
(DLGPROC)DialogProc);
}
The second example does not contain any call to the register function. It just creates the DialogBox with its DialogProc process attached.
This works fine, but I am wondering if there is a benefit of registering the window class and then creating the dialog box (if this is at all possible).
You do not have to register a dialog box.
Dialog boxes are predefined so (as you noted) there is no reference to a window class when you create a dialog. If you want more control of a dialog (like you get when you create your own window class) you would subclass the dialog which is a method by which you replace the dialogs window procedure with your own. When your procedure is called you modify the behavior of the dialog window; you then might or might not call the original window procedure depending upon what you're trying to do.
It's been a while since I've done this, but IIRC, the first case is for creating a dialog dynamically, from an in-memory template. The second example is for the far more common case of creating a dialog using a resource. The dynamic dialog stuff in Win32 was fairly complex, but it allowed you to create a true data-driven interface, and avoid issues with bundling resources with DLLs.
As for why use Win32 - if you need a windows app and you don't want to depend on MFC or the .NET runtime, then that's what you use.