How to add a custom button to windows' minimize/maximize/close (x) - windows

I was wondering if there is a way to add (programatically, of course) an icon/button/whatever besides plain text to a window (Microsoft Windows window...)'s title bar or next to where the minimize/maximize/close buttons are. I could draw it myself and create an illusion it is a part of the window, but I wonder if in the user32 api there is such a method.
So far, I found a way to disable the minimize/maximize/close buttons but not a way to add a custom one to them. It seems strange to me.
Here is what I am trying to achieve:
I have been wondering how it is done here, since drawing a button for every window using gdi/gdi+ and then detecting if it is overlapped by another window and then displaying only the non-overlapped part seems to me like an unlikely solution. Probably the button has been registered in the window class so that every window has this button. Any pointers what to do?
In addition, how do I create a button at all, assuming I DON'T have Unicode enabled. Then in the following piece of code:
HWND hwndCommandLink = CreateWindow(
L"BUTTON", // Class; Unicode assumed.
L"", // Text will be defined later.
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_COMMANDLINK, // Styles.
10, // x position.
10, // y position.
100, // Button width.
100, // Button height.
hDlg, // Parent window.
NULL, // No menu.
(HINSTANCE)GetWindowLong(hDlg, GWL_HINSTANCE),
NULL); // Pointer not needed.
SendMessage(clHwnd, WM_SETTEXT, 0, (LPARAM)L"Command link");
SendMessage(clHwnd, BCM_SETNOTE, 0, (LPARAM)L"with note");
I have to substitute all the nice Windows constants with their long equivalent....However, when I search for them, all i get is this:
http://msdn.microsoft.com/en-us/library/bb775951(v=VS.85).aspx
Any pointers?

Related

How to get rect of the item in Listbox using winapi

I am using VC6.0. I am trying programming to show contextmenu when I right click on the item of the ListBox. But now the popmenu can show anywhere in the rect of ListBox, since I only can get the rect of the ListBox, and I dont know how to get the rect of the item. I know that there is a macro ListView_GetSubItemRect which seems to get the rect of item of ListView. Is there similar way for ListBox, or is there a way to get the width and the height of item of ListBox, so I can caculate the rect? I didnt find some useful information on msdn and google? Can anyone give me some ideas? Thanks.
My current Code:
void My_OnContextMenu(HWND hwnd, HWND hwndContext, UINT xPos, UINT yPos)
{
HWND hList = GetDlgItem(hwnd,IDC_LIST_RESTYPE);
if (hList == hwndContext)
{
if(-1!=indexLB)
{
RECT rect;
POINT pt;
GetClientRect(hwndContext, &rect);
ScreenToClient(hwndContext, &pt);
if(PtInRect(&rect, pt))
{
HMENU hroot = LoadMenu((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), MAKEINTRESOURCE(IDR_MENU_DELTYPE));
if(hroot)
{
HMENU hpop = GetSubMenu(hroot,0);
ClientToScreen(hwndContext, &pt);
TrackPopupMenu(hpop, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwndContext, NULL);
DestroyMenu(hroot);
}
}
}
}
}
Edit
Current:
First, I left click an item to selected、 an item. And Second I right click the selected item to show popmenu. It shows normally. But in the second step if I click the blank area of ListBox, it shows menu either. That is not what I expected.
What I expected is:
The menu only shows when I click an item and the position only over the item. When I right click other area, it wont be showed.
You are looking for the ListBox_GetItemRect macro.
However, I do feel that the user will find it odd to click in one place and see the menu appear somewhere else.
The proper solution to this problem is to popup the context menu at the mouse position. Clicking in one place and popping it up somewhere else would be very bad.
To get the mouse position use GetCursorPos().
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648390%28v=vs.85%29.aspx
To be clear, first use ListBox_GetItemRect to work out which item is clicked on, and ignore it if none. Then use GetCursorPos so the menu appears exactly where the mouse is -- inside the list item -- and not somewhere a few pixels away. The Windows UI standards are that the context menu appears at the cursor position.
I'm not sure Why you wrote your own OnContextMenu - you should use the class wizard to map WM_CONTEXTMENU with the standard handler where the existing function ends up in your code like this:
//Wizard Added this the message map block
ON_WM_CONTEXTMENU()
//Declares the function with the proper parameters
void MyDlg::OnContextMenu(CWnd* pWnd, CPoint point);
//in the body of OnContextMenu use the system supplied parameters and the
//menu will appear next to the mouse position wherever it is clicked in the control
CMenu popupmenu;
popupmenu.LoadMenu(IDR_RMOUSEPOPUP);
int Command = (int)popupmenu.GetSubMenu(0)->TrackPopupMenu(
TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY,
point.x, point.y, pWnd);

WinApi - How To Modify Console Window?

I want my console window to be modified. I got the handle. And this helps to change it. But how can I
remove close button
remove maximize button
remove icon
disable resizing
?
// C# syntax
StringBuilder buffer = new StringBuilder(260);
IntPtr window = FindWindow(null, buffer.ToString(0, GetConsoleTitle(buffer, buffer.Capacity)));
uint a = (uint)((WS_BORDER | WS_CAPTION) & (~WS_ICONIC));
SetWindowLongPtr(window, -16, new IntPtr(a)); // GWL_STYLE = -16
For some reason the window is broken after this call. I can't move it with the mouse anymore and all clicks go through it to other windows.
You removed all the window styles, and added back just WS_BORDER and WS_CAPTION. What you should do is:
Read the current window style with a call to GetWindowLongPtr.
Perform bitwise AND with the bitwise negation of the styles you want to remove.
Set the window style with a call to SetWindowLongPtr.

Deactivating desktop background when a pop up is shown to user

I have a win32 application that runs full screen when started. The application has some button which invoke pop up dialogs.
Is there a way to make the entire desktop (except the pop up) go transparent black unless the pop up is dismissed by the user? what I am talking of is similar to windows 7 UAC pop ups and the background it causes.
Is it possible to do similar stuff for a full screened window app?
It is possible do this…sort of. Perhaps I should say, you can simulate this effect. It won't actually be like the UAC dialog, as the user will still be able to interact with other running applications. There is no such concept as "system modal" available to applications. That's by design, of course. But you can certainly show a "light box" that dims out the rest of the desktop and forces focus on your app's dialog box.
The way I would do it is to create a giant layered window that sits on top of all other windows and covers the entire screen, fill it with black, and set the opacity as desired. Then, before you show a modal dialog (either by calling the MessageBox function or using the DialogBox function to show one of your own custom dialogs), display your light box window. Finally, after the user dismisses the modal dialog, you will destroy the light box window.
Here's some sample code. Error checking is omitted for brevity. So is other good style, like wrapping this mess up in one or more classes.
INT_PTR ShowLightBoxedDialog(HINSTANCE hInstance,
LPCTSTR pDlgTemplate,
HWND hwndParent,
DLGPROC pDlgProc,
BYTE opacityLevel)
{
const TCHAR szLightBoxClass[] = TEXT("LightBoxWndClass");
// Register the light box window class.
static bool lightBoxRegistered = false;
if (!lightBoxRegistered)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(wcex);
wcex.style = CS_NOCLOSE | CS_SAVEBITS;
wcex.lpfnWndProc = LightBoxWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hIconSm = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szLightBoxClass;
RegisterClassEx(&wcex);
lightBoxRegistered = true;
}
// Create and display the light box window.
HWND hwndLightBox = CreateWindowEx(WS_EX_NOACTIVATE | WS_EX_LAYERED,
szLightBoxClass,
NULL,
WS_POPUPWINDOW,
0, 0, 0, 0,
hwndParent,
NULL,
hInstance,
NULL);
SetLayeredWindowAttributes(hwndLightBox, 0, opacityLevel, LWA_ALPHA);
SetWindowPos(hwndLightBox,
HWND_TOP,
GetSystemMetrics(SM_XVIRTUALSCREEN),
GetSystemMetrics(SM_YVIRTUALSCREEN),
GetSystemMetrics(SM_CXVIRTUALSCREEN),
GetSystemMetrics(SM_CYVIRTUALSCREEN),
SWP_SHOWWINDOW);
// Display the modal dialog box (as you normally would).
// NOTE: The dialog box won't appear centered on the screen.
// For that, you will need to write centering code in response
// to the WM_INITDIALOG message in the dialog procedure.
INT_PTR result = DialogBox(hInstance, pDlgTemplate, hwndLightBox, pDlgProc);
//
// For demonstration purposes, I used the following code:
// INT_PTR result = MessageBox(hwndLightBox,
// TEXT("OH NOEZ!\n\nYour system is kaput! Abandon þe all hope."),
// NULL,
// MB_ABORTRETRYIGNORE | MB_ICONERROR);
// Destroy the light box window.
DestroyWindow(hwndLightBox);
// Return the result of the modal dialog box.
return result;
}
You'll notice that basically what I've done is created a wrapper around the DialogBox function, which you use whenever you want a dialog box with a "light box" effect. It takes all of the same parameters (the first 4), and then there's an additional one tacked on the end that allows you to specify the opacity level used for the "light box" effect. Something in the range of 150–200 is probably good. Naturally, you could pick something and hard-code it, but I suffer from severe allergies to hard-coded values. Anyway, it's super easy to call this function from anywhere:
ShowLightBoxedDialog(hInstance, /* your application instance */
MAKEINTRESOURCE(IDD_SAMPLE), /* your dialog template */
hWnd, /* parent window for dialog */
SampleWndProc, /* ptr to dialog procedure */
175); /* light box opacity level */
Because the code takes advantage of how modal dialogs already work in Windows, the user won't be able to interact with any other pieces of your application until they dismiss the dialog box. And because the "light box" window is positioned on top of everything else, it eats all mouse clicks and prevents setting focus to any other application. But it is trivial to work around using something like Alt+Tab.
So this is not a security feature! It is merely a visual effect!
And because it's just a silly visual effect, it's likely to be a frustrating one for your users. I don't actually recommend using it. But now you know how to do it. Wield such power responsibly, etc.

Win32 GUI: dialog in dialog

I just started to use dialogs and I really like the possibility to define the layout in resource file. But is it possible to set up one dialog and embed it into another (i.e., no floating dialogs)?
With plain windows, I created the main window with one child window. Then, I created even more windows (like "edit", "static", ...) and added them to the child. I did so in order to group those several windows in to one window so I can control, say, the visibility of all edits and statics easily. Kind of like grouping (but it doesn't have the border of GroupBox).
Is it possible to rewrite the above, but with dialogs written down in .rc file?
I'm using plain C and Win32.
Example of what I did:
main = CreateWindow(...);
container = CreateWindow(... hWndParent = main ...);
label = CreateWindow("static", ... container);
edit = CreateWindow("edit", ... container);
Now, if I can hide or resize both label and edit just but controlling container.
Example of what I would like to have:
MAIN_DIALOG DIALOG 10, 20, 30, 40 STYLE ...
BEGIN
CONTROL "container" ...
END
How do I add 'label' and 'edit' to "container" control?
Also, in the resource editor set the dialog style to 'child' and border to 'none'.
What you want to do is probably a little bit similar to tabbed dialogs. There some controls are embedded from separate resources with a outer dialog. You can then show/hide all the controls within a tab by calling ShowWindow just for the subdialog:
In you main dialog Callback add something like
HWND SubDlgHwnd; // Global or probably within a struct/array etc.
case WM_INITDIALOG:
{
HRSRC hrsrc;
HGLOBAL hglobal;
hrsrc = FindResource(sghInstance, MAKEINTRESOURCE(SubDlgResId), RT_DIALOG);
hglobal = ::LoadResource(sghInstance, hrsrc);
SubDlgHwnd = CreateDialogIndirect(sghInstance, (LPCDLGTEMPLATE)hglobal, hDlg, ChildDialogCallback);
SetWindowPos(SubDlgHwnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
break;
}
case WM_COMMAND:
{
...
if(UpdateVisibility)
ShowWindow(SubDlgHwnd, showSubDialog ? SW_SHOW : SW_HIDE);
}
This might be a good Startpoint for Microsofts documentation.
You also have to add DS_CONTROL style to the dialog(s) you want to embed. Without it embedded dialog window will be shown with window header what is hardly one wants to.

Capturing a Window that is hidden or minimized

I followed this tutorial (there's a bit more than what's listed here because in my code I get a window via mouse click) for grabbing a window as a bitmap and then rendering that bitmap in a different window.
My question:
When that window is minimized or hidden (SW_HIDE) my screen capture doesn't work, so is it possible to capture a window when it is minimized or hidden?
The PrintWindow api works well, I use it for capturing thumbnails for hidden windows. Despite the name, it is different than WM_PRINT and WM_PRINTCLIENT, it works with pretty much every window except for Direct X / WPF windows.
I added some code (C#) but after reviewing how I used the code, I realized that the window isn't actually hidden when I capture its bitmap, its just off screen so this may not work for your case. Could you show the window off screen, do a print and then hide it again?
public static Bitmap PrintWindow(IntPtr hwnd)
{
RECT rc;
WinUserApi.GetWindowRect(hwnd, out rc);
Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
Graphics gfxBmp = Graphics.FromImage(bmp);
IntPtr hdcBitmap = gfxBmp.GetHdc();
bool succeeded = WinUserApi.PrintWindow(hwnd, hdcBitmap, 0);
gfxBmp.ReleaseHdc(hdcBitmap);
if (!succeeded)
{
gfxBmp.FillRectangle(new SolidBrush(Color.Gray), new Rectangle(Point.Empty, bmp.Size));
}
IntPtr hRgn = WinGdiApi.CreateRectRgn(0, 0, 0, 0);
WinUserApi.GetWindowRgn(hwnd, hRgn);
Region region = Region.FromHrgn(hRgn);
if (!region.IsEmpty(gfxBmp))
{
gfxBmp.ExcludeClip(region);
gfxBmp.Clear(Color.Transparent);
}
gfxBmp.Dispose();
return bmp;
}
There are WM_PRINT and WM_PRINTCLIENT messages you can send to the window, which cause its contents to be rendered into the HDC of your choice.
However, these aren't perfect: while the standard Win32 controls handle these correctly, any custom controls in the app might not.
I am trying to get the bitmap of partially hidden controls.
I used code before that did the drawing, but included windows overlapping it. So.. maybe you want to try this.
The WM_PRINTCLIENT should (in my understanding) redraw all inside the control, even if it is not really visible.
const int WM_PRINT = 0x317, WM_PRINTCLIENT = 0x318, PRF_CLIENT = 4,
PRF_CHILDREN = 0x10, PRF_NON_CLIENT = 2,
COMBINED_PRINTFLAGS = PRF_CLIENT | PRF_CHILDREN | PRF_NON_CLIENT;
SendMessage(handle, WM_PRINTCLIENT, (int)hdc, COMBINED_PRINTFLAGS);
//GDIStuff.BitBlt(hdc, 0, 0, width, height, hdcControl, 0, 0, (int)GDIStuff.TernaryRasterOperations.SRCCOPY);
The before code is commented out now. It is based on the code found here: Pocket PC: Draw control to bitmap (accepted answer). It is basically the same as Tim Robinson suggests in this thread.
Also, have a look here
http://www.tcx.be/blog/2004/paint-control-onto-graphics/

Resources