So I have a window, and I have coded it so that during run-time it can enter and exit full-screen mode. Entering full-screen works, but exiting places the window tile bar in reverse order.
Exit full screen code:
SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_OVERLAPPEDWINDOW);
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 640, 480, NULL);
InvalidateRect(hWnd, NULL, TRUE);
Picture of the result: https://www.dropbox.com/s/p15eltz7b2hxx4y/window.png?dl=0
I tried using GWL_STYLE instead of GWL_EXSTYLE but that works even worse, with the window being visible but clicking anything on the window will act like the window is not there and the click on whatever is behind it...
Thanks!
Philip
Just a thought, couldn't you get the window style (with GetWindowLongPtr), store it as a member variable in you class and then use this as the style to reset in SetWindowLongPtr?
Following is uncheck code (this is assuming you are using C++),
MainWnd::OnFullScreen(...)
{
m_oldStyle = GetWindowLongPtr(GWL_EXSTYLE, m_hwd);
/*
what ever other code is necessary
*/
}
MainWnd::OnExitFullScreen(...)
{
SetWindowLongPtr(m_hwn, GWL_EXSTYLE, m_oldStyle);
/*
and other code as needed
*/
}
I've made two assumptions here:
(1) that you will have two variables, one to contain the old style (m_oldStyle) and one to hold the handle to the window (m_hwd). Note if you are doing strict SDK style coding then the handle will be passed to you as part of WndProc. If you are using MFC there should be member function in the class you derived you main window from. In other cases you are on your own.
(2) the second assumption is that SetWindowLongPtr is called prior to any change of screen type. I believe that SetWindowLongPtr is called during window construction, but it has been several years since I've done serious windows programming using Microsoft frameworks (now I tend to used QT's framework).
Related
Background
I am trying to screenshot a specific window, however the OS where I need to accomplish this has very high CPU usage and sometimes my application determines this window as visible however in the screenshot it is either not shown or half drawn.
My Understanding
Since the CPU usage is very high it will not be able to provide enough resources to the process which opens this specific window. Therefore the check for window visibility succeeds it may just mean that the window was initiated for creation but not drawn yet (given the lack of resources).
My Code
HWND hWnd = FindWindowExA(0, 0, NULL, programdata->caption);
if (hWnd)
{
if (IsWindowVisible(hWnd))
{
RECT rect = { 0 };
GetWindowRect(hWnd, &rect);
// if window size also matches requirement then
TakeScreenshot();
Question
Is there any better way that I can determine if the window was fully drawn and visible to the human eye?
if the window was fully drawn and visible to the human eye?
To take screenshot you don't need the window to be visible. You only have to copy from its context. So just do GetWindowDC() and use it.
If you really need to check if it's "visible to human eye", you must also ensure that the window is at the top of Z-order. Otherwise, it could be overlayed by some other window.
If you want to check if window was fully repainted, you can test its GetUpdateRect() value.
Problem description
I want to create a Windows API app in C which renders the menu and the caption buttons in the same non-client area, similar to Firefox
In order to do this, I've determined the solution needs to:
be type WS_POPUP, in order for the menu to be aligned to the top
take ownership of the non-client area (where the menu is rendered)
manually render the minimize/maximize/close buttons
The solution needs to work on Windows 7, 8, and 10 (and ideally future versions too).
How it looks now
I have a test program available on GitHub.
In my app, I've overridden the appropriate events:
WM_NCCALCSIZE, WM_NCHITTEST, WM_NCLBUTTONDOWN, WM_NCLBUTTONUP, WM_NCMOUSEMOVE, WM_NCPAINT
And then I repaint non-client areas on these events:
WM_NCACTIVATE, WM_SETTEXT
Here's an example of how I'm doing the rendering:
// globals set elsewhere
RECT customAreaRect, minRect, maxRect, closeRect, coverMenuRect;
BOOL maximized;
// ...
LRESULT OnPaintNCA(HWND hWnd, WPARAM wParam, LPARAM lParam) {
RECT windowRect;
HRGN hRgn = NULL;
GetWindowRect(hWnd, &windowRect);
if (wParam == 1) {
hRgn = CreateRectRgnIndirect(&windowRect);
} else {
hRgn = (HRGN)wParam;
}
if (hRgn) {
// Carve out the area for custom content
HRGN captionButtonRgn = CreateRectRgnIndirect(&customAreaRect);
CombineRgn(hRgn, hRgn, captionButtonRgn, RGN_XOR);
DeleteObject(captionButtonRgn);
// Force default painting for non-client area
LRESULT ret = DefWindowProc(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0);
// black background covering part of menu, behind buttons
HDC hDC = GetWindowDC(hWnd);
FillRect(hDC, &coverMenuRect, (HBRUSH)GetStockObject(BLACK_BRUSH));
HTHEME hTheme = OpenThemeData(hWnd, TEXT("WINDOW"));
DrawThemeBackground(hTheme, hDC, WP_MINBUTTON, partState, minRect, NULL);
DrawThemeBackground(hTheme, hDC, maximized ? WP_RESTOREBUTTON : WP_MAXBUTTON, partState, maxRect, NULL);
DrawThemeBackground(hTheme, hDC, WP_CLOSEBUTTON, partState, closeRect, NULL);
CloseThemeData(hTheme);
}
}
The rendered result looks like this:
Unfortunately, the styles used for the parts (minimize, maximize/restore, close) look like the styles for Windows 7/8, and not the native Windows 10 controls. I've been searching for a way to do this for several days without luck. I need help understanding how to render these buttons for Windows 10 using the Windows API.
Current status (and what I've tried so far)
My first hunch was that I need to properly enable Visual Styles.
Per this article, calls checking the OS version will get Windows 8 unless you specifically target Windows 10 via a manifest. Click here to view my manifest. This does work:
Before GetVersionEx returned major=6, minor=2, build=9200
Now GetVersionEx returns major=10, minor=0, build=10586
Per the official "Enabling Visual Styles" article, I made sure to use Common Controls version 6.
Added linker input for Comctl32.lib
Call is made to InitCommonControls on program start
Added dependency for version 6 to the application manifest
Here are some screenshots of relevant project settings that I have tried:
Other ideas
I'm running low on things to try. Before throwing in the towel, there were some things I was going to try:
Idea 1: using GetThemeStream which allows you to retrieve the size/bitmap for controls.
Load aero msstyles file like so:
HMODULE themeFile = LoadLibraryEx(TEXT("C:\\Windows\\Resources\\Themes\\aero\\aero.msstyles"), NULL, LOAD_LIBRARY_AS_DATAFILE);
Get the bitmap for the part (minimize button, maximize button, etc) like so (passing the loaded theme file):
GetThemeStream(h, WP_MAXBUTTON, MAXBS_NORMAL, TMT_DISKSTREAM, (void**)&buffer, &bufferSize, themeFile);
Load the bitmap; it appears to be in PNG format (I haven't gotten this far)
Draw the bitmap
Idea 2: copy the non-client area from a hidden window which has the caption area (and minimize, maximize, close buttons).
Create a window which has the caption and min/max buttons, never activating it.
In the non-client paint, get the DC for that Window and capture the pixels for the min/max/close button
Render them using bitblt
I think the issue comes from trying to use WM_NCPAINT on OS version >= Win Vista.
Since Vista all NC rendering is controlled by DWM (desktop window manager). If you still dare to handle WM_NCPAINT, DWM rendering will be turned off and you get "old-school" look:
From the Shell Revealed Blog:
The DWM doesnt have any legacy worries because applications cannot
draw inside the glass frame, since its rendered and managed by a
totally different process. If an application tries to do it, Windows
will detect it and remove the glass frame entirely (and therefore
revert to the Basic frame), so that the application can draw what it
wants to draw.
To get proper results, you have to do it the "DWM way" (specifically the sections "Removing the Standard Frame" and "Drawing in the Extended Frame Window"). This works by letting DWM render the frame within the client area, so you can paint over it. Also with this solution you don't have to draw the caption buttons on your own. This answer summarizes the required steps (under "Aero supported solution").
The caveat is that you propably have to draw the menu on your own and you can't use most of GDI API for that, because GDI ignores the alpha channel and things will look ugly if the frame is translucent (Vista and Win 7 by default, Win8+ with extensions). BitBlt() works if the source is a memory DC that contains a 32bpp bitmap with an alpha channel. GDI+ works aswell.
I'm using the ChooseFont system dialog to populate a LOGFONT structure that is passed to CreateFontIndirect and the resulting font handle is selected into the device context and used. But it doesn't resemble the requested font in any way (well, OK, similar character sets, but otherwise not the same). Here's an image of the screen showing the ChooseFont dialog selecting an old DOS-style VGA font and in the background (behind the ChooseFont dialog) shows the font that I got when I selected the values shown in the dialog:
Notice that the Sample in the dialog and what Windows puts on the screen when the created font is selected into the DC are quite different. This doesn't happen for ALL fonts, only some of them, which is why I'm trying to correct and/or detect this.
I've tried getting the LOGFONT for the new font from the DC using (GetCurrentObject and GetObject) and it is identical to my request, except that the lfQuality has changed to NONANTIALIASED_QUALITY from anything else I've tried setting it to.
I have a kinda two part question:
How can I force Windows to use the font I've selected. Obviously there is a way, or it wouldn't look right in the ChooseFont dialog, either.
If no one can answer #1, how can I reliably find out that Windows has selected a totally wrong font, when asking Windows for the font info about the created font when selected into the device context doesn't work?
EDIT: July 8
If this helps at all, my basic calling sequence is:
LOGFONT lf;
CHOOSEFONT cf;
HFONT hf;
cf.lpLogFont = &lf; // plus other necessary stuff
ChooseFont( &cf );
hf = CreateFontIndirect( &lf );
SelectObject( hdc, hf );
ExtTextOut( hdc, ... );
Then, when I use the font, it doesn't always match what I requested. At all. (I just tried using Arial Monospaced MT and was rewarded with Courier -- Lucida Console would be a better substitute, at least it doesn't have serifs!) I don't do ANYTHING to the DC other than call GetDC(). I don't call any GDI setup/configuration functions, either, so I'm in whatever default mode one gets with a standard Windows program written in C to the WIN32API.
I've discovered that the Windows version of PuTTY shows the correct fonts while my program doesn't, but I have not yet been able to find anything different between the functions/parameters it uses to handle font creation and the way I do it. I'll keep looking though. Thanks to anyone who's given my question any thought, with or without suggestions. :-)
I have WPF window in which my Direct3D engine render. WPF Window I start from my engine, which I develop on C++/CLI.
I have 2 displays and when I move window between them, part of the window became white and not update until I am not stop dragging it (like on screen shot).
Does somebody know how to fix this issue?
It will be hard to post code here as it is a lot of code, but I will try:
I use managed C++ and unmanaged in one project:
So, I add .Net dll`s to have access to the WPF window:
Window^ wnd = gcnew Window();
wnd->Width = 1280;
wnd->Height = 720;
wnd->Show();
WindowInteropHelper^ helper = gcnew WindowInteropHelper(wnd);
HWND WPFHwnd = (HWND)helper->Handle.ToPointer();
HINSTANCE hinstance = (HINSTANCE)Marshal::GetHINSTANCE(this->GetType()->Module).ToPointer();
engine->SetHisnstanceHWND(WPFHwnd, hinstance);
engine->InitializeSystem(wnd->ActualWidth, wnd->ActualHeight);
engine - this is unmanaged class which incapsulates all work with rendering.
Further it is a stardard d3d rendering loop. Nothing special.
It render OK, but when I resizing or move window, it draw a part of it like this (with white). When I stop resizing or moving - all OK again.
My question is: is it possible to get rid of this effect or not?
UPDATE:
I hooked the wndProc if the WPF window and try to use UpdateLayout() when size changing, but this has no effect. Seems window is not react on any intervention.
Well, it sounds like your engine is receiving WM_ERASEBKGND and it clears the window. After you release the window, it sends WM_PAINT and everything is clear again. That's what I believe might be happening.
In order to test this theory, you can handle that message and return true. Put that to your engine message handling routine:
case WM_ERASEBKGND:
{
PAINTSTRUCT pss;
BeginPaint(hWnd,&pss);
EndPaint(hWnd,&pss);
return true;
}
You can use WinSpy++ to check out what messages are delivered to underneath window. If you want to see why the background is whited out, you can do it through ProcessMonitor and see what API calls are being issued. You're probably interested in API calls that include the color white.
I have a WIN32 application. Its main window is hwndMain, one of its child is hwndView. There is one tab control hwndTab on hwndView.
When I resize hwndMain, hwndView is resized and so is hwndTab. It flicker a little, but not much.
I have tried to use WS_EX_COMPOSITED style ( for hwndView or hwndTab), but it just gave me blank window. I tried to use WS_EX_TRANSPARENT and it solves flicker, but when the windows is resized to be larger, the childs are updated very slow, e.g I see black region for one second, then the region is updated.
I have successfully sloved the flicker issue for TreeView by using WS_CHIPCHILDREN style. (See remark below). But using WS_CHIPCHILDREN stlye for hwndView doesn't fix the flicker issue for tab control.
I have paid attention to WM_ERASEBKGND and Not set hbrBackground also.
I want to use double buffer for tab control, but I can't find a tutorial for this purpose. All the tutorial I found is: In WM_PAINT, after creating CompatibleDC and CompatibleBitmap, draw what you want in memdc and.....; But I don't want to do any custom drawing in WM_PAINT for hwndTab. I just want to leave the tab control do this job, but shows the final result only.
Could someone show me a small example how to double buffer a tab control (if you think this will fix the flicker issue of tab control), in the language c + winapi, since I don't have the knowledge of C#, Net,..etc.
Remark: For my TreeView, it is a child of a window hwndContainer. It is created as:
win->hwndContainer = CreateWindowEx(
WS_CLIPCHILDREN,
_T("SUMATRA_PDF_TOCBOX"), NULL,
WS_CHILD,
0, 0, gGlobalPrefs.sidebarDx, 0,
win->hwndPanel, NULL,
ghinst, NULL);
Using WS_CLIPCHILDREN fix the flicker, even if I don't use double buffer. But it is strange to put
WS_CLIPCHILDREN in the first parameter position. If I put it after WS_CHILD, i.e
win->hwndContainer = CreateWindowEx(
NULL,
_T("SUMATRA_PDF_TOCBOX"), NULL,
WS_CHILD | WS_CLIPCHILDREN,
0, 0, gGlobalPrefs.sidebarDx, 0,
win->hwndPanel, NULL,
ghinst, NULL);
,then the flicker still occurs.
So I also tried to use the first way when I created hwndView, but it just gave blank white window.
I am really confused with these stuff.
Here is the blank window picture when I used WS_EX_COMPOSITED for hwndView.
There is no such problem when I used it for hwndContainer.
hwndView in fact has two child: a Tab Control hwndTab and a child which has its own double buffer and drawing. I am not sure if this cause the problem for using WS_EX_COMPOSITED.
You are using the WS_EX_COMPOSITED style. When you pass WS_CLIPCHIDREN as the first argument to the CreateWindowEx, it's interpreting the value of WS_CLIPCHILDREN as an extended window style. Since the value of WS_CLIPCHILDREN is 0x02000000L, the same as WS_EX_COMPOSITED, you've just created a composited window.
And a composited window, according to the documentation, has all of its descendants painted in a bottom-to-top painting order using double-buffering.
I'm not sure what you mean when you say:
I have tried to use WS_EX_COMPOSITED style ( for hwndView or hwndTab), but it just gave me blank window.
You'll have to post code the reproduces this problem. But your second-to-last code snippet is producing a composited window.