WinApi - How To Modify Console Window? - winapi

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.

Related

How can I remove the border on a Dialog Window with Dynamic Layout controls?

I have a WIN32 application that uses a main dialog window as background and several alternative dialogs that can appear in front of the main window. These overlay dialogs should not have any border because they need to appear to be part of the main window.
Everything was working well until I activated Dynamic Layout on the controls in an overlay dialog. It then acquired a thin border with drop shadow, a thin top bar that was sometimes windows top bar color and sometimes white, and the dialog became independently resizable. I don't want this, I want the overlay dialog to resize only with the main dialog window.
How can I force the dialog to have No Border?
You can modify the style of a dialog window in your override of the OnInitDialog() member function, if that window is created using a custom class derived from CDialog or CDialogEx, or something similar. (If not, you'll need to somehow 'intercept' the window's creation process.)
Assuming you have overridden OnInitDialog(), the process will be along these lines:
BOOL MyDialog::OnInitDialog()
{
BOOL answer = CDialog::OnInitDialog(); // Call base class stuff
LONG_PTR wStyle = GetWindowLongPtr(m_hWnd, GWL_STYLE); // Get the current style
wStyle &= ~WS_BORDER; // Here, we mask out the style bit(s) we want to remove
SetWindowLongPtr(m_hWnd, GWL_STYLE, wStyle); // And set the new style
// ... other code as required ...
return answer;
}
Note: It is important to call the base class OnInitDialog() before you attempt to modify the window's style; otherwise, the window may not be in a 'completed' state, and any changes you make may be reverted.
As mentioned in the comment by IInspectable, it may be possible (or even better) to modify the style (taking out the WS_BORDER attribute) in an override of the PreCreateWindow() function:
BOOL MyDialog::PreCreateWindow(CREATESTRUCT &cs)
{
if (!CDialog::PreCreateWindow(cs)) return FALSE;
cs.style &= ~WS_BORDER;
return TRUE;
}
Again, as shown here, you should call the base class member before modifying the style.
So the answer to my original question is to put the following code in the overloaded OnInitDialog() after the call to the base class.
LONG_PTR wStyle = GetWindowLongPtr(m_hWnd, GWL_STYLE); // Get the current style
wStyle &= ~WS_SIZEBOX; // Mask out the style bit(s) we don't want
SetWindowLongPtr(m_hWnd, GWL_STYLE, wStyle); // And set the new style

Get the last ShowWindow state for a window in winapi

When you click a window in your taskbar (Windows users) it will retain it's last state - maximised or normal scalable window. I'm trying to do a similar thing, but programatically and without the window gaining focus (eg. becoming foreground and disturbing my current activity in another window).
Can I do that? Current window state can be obtained using this API call:
//Empty Window placement structure
WinDefExt.WINDOWPLACEMENT placement = new WinDefExt.WINDOWPLACEMENT();
//winapi call to external User32.dll file
UserExt.GetWindowPlacement(hwnd, placement);
//showCmd should be equal to one of the SW_ constants (here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548%28v=vs.85%29.aspx)
placement.showCmd;
ShowWindow isn't a "state", it's an "action". There's no GetShowState command. You can infer a value from the current state of the window, but there's no way to find out the actual last value used with ShowWindow.
if (!IsWindowVisible(hWnd))
swState = SW_HIDE;
else
if (IsIconic(hWnd))
swState = SW_MINIMIZE;
else
if (IsZoomed(hWnd))
swState = SW_MAXIMIZE;
else
{
// not hidden, minimized or zoomed, so we are a normal visible window
// last ShowWindow flag could have been SW_RESTORE, SW_SHOW, SW_SHOWNA, etc
// no way to tell
swState = SW_SHOW;
}

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.

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

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?

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