I want to change my windo style during runtime. I use this code
if (this->fullscreen)
{
this->style = WS_POPUP|WS_VISIBLE;
}
else
{
this->style = WS_OVERLAPPED|WS_SYSMENU|WS_VISIBLE;
}
SetWindowLongPtr(this->mainWindowHandle, GWL_STYLE, this->style);
SetWindowPos(this->mainWindowHandle,
HWND_TOP,
0,
0,
0, //New Width
0, //New Height,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
But it has no effect... and window is still without border (WS_POPUP)...
According to MSDN, you can't modify those particular styles after the window is created. If you're going to try to anyway, it also says that WS_SYSMENU requires WS_CAPTION.
Try calling SetWindowPos with the flag SWP_DRAWFRAME and see if it helps.
You might need to use CWnd::ModifyStyle. Have a look at example here
You might save the current pos and size from the actual window. Then destroy it an create an new window with the new style, previous pos and size.
Related
I am trying to keep my window on top of the all others. I am new to C++ Win32 programming. This is my initialization of my window in WinMain:
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
I previously worked with dialogs, so the topmost property was really easy to use. But here, on a window I don't know how to set it. I also want to be able to trigger it. Can anybody help me?
SetWindowPos(hwnd01, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
Note: SWP_NOMOVE | SWP_NOSIZE are for ignoring 3rd, 4th, 5th, 6th parameters of the SetWindowPos function.
The second parameter can be:
HWND_BOTTOM
HWND_NOTOPMOST (set window to be a normal window)
HWND_TOP
HWND_TOPMOST (set window to be always on top)
Use CreateWindowEx with (extended) window style WS_EX_TOPMOST.
Disclaimer: it's about 15 years or so since I touched that stuff.
see SetWindowPos, hWndInsertAfter parameter. passing HWND_TOPMOST should do what you want.
additionally, you may want to pass SWP_NOMOVE | SWP_NOSIZE to uFlags parameter if you want to keep position and size unchanged.
SWP_NOMOVE Retains the current position (ignores X and Y parameters).
SWP_NOSIZE Retains the current size (ignores the cx and cy parameters).
If you don't set these flags you should specify position and size instead of passing 0, 0, 0, 0
I'm having problems with the follow code
int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
{
return -1;
}
DWORD dwStyle = LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP | WS_CLIPSIBLINGS | WS_CHILD;
CMFCListCtrl TempCtrl;
TempCtrl.Create(dwStyle, CRect(0, 0, 0, 0), this, IDC_FILTERLIST);
CMFCHeaderCtrl& HeaderCtrl = TempCtrl.GetHeaderCtrl();
if (!::IsWindow(HeaderCtrl.GetSafeHwnd()))
{
AfxMessageBox("Failed to create CMFCListCtrl properly!");
}
....
The header control part of the CMFCListCtrl is not getting created/initialized correctly. Does anyone have an idea what I'm doing wrong? Any help would be appreciated.
I noticed that you are creating a control inside a CView-derived class. Please note that the id must start from the value AFX_IDW_PANE_FIRST. Otherwise it will fail. Just google AFX_IDW_PANE_FIRST and you'll find the explanation why.
So, just replace your line with:
TempCtrl.Create(dwStyle, CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST);
I solved the above problem by using the WS_VISIBLE style at creation, but I still don't understand why this is so.
I'm wondering if it's possible to toggle back and forth between fullscreen mode and windowed mode in an OpenGL window(I'm writing for Windows using C++ and win32), without destroying the OpenGL context, and thus having to reload assets(Textures, VBOs, etc) in the process?
This is undesirable because it introduces a delay in switching between fullscreen and windowed mode, potentially a long one, as well as making it easier to screw things up by forgetting to reinitialize something.
As a followup to that, are there certain visual effects that are broken by managing to do this?
I've done a fair bit of searching and reading for the past few days, and despite a lot of flaming of SDL and other frameworks for having the same problem(I'm not using them anyway, but...), the best I've managed to find is a possible lead on opening a 1x1 window in the background to retain the context while a secondary window is destroyed or created at whim. And that's seeming unreliable from the comments I found regarding it, and seems very kludgey regardless.
Is there a proper way to do this, or is the proper way the often-given-as-an-example method of destroying your window, and recreating it, including destroying your OpenGL context and recreating it?
Basically it's just resizing the window and specifying flags that the border is invisible.
SetWindowLongPtr(hWnd, GWL_STYLE,
WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE);
MoveWindow(hWnd, 0, 0, width, height, TRUE);
to set it back:
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = width;
rect.bottom = height;
SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
MoveWindow(hWnd, 0, 0, rect.right-rect.left, rect.bottom-rect.top, TRUE);
or for a not-resizable window:
SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE);
AdjustWindowRect(&rect, WS_CAPTION | WS_POPUPWINDOW, FALSE);
MoveWindow(hWnd, 0, 0, rect.right-rect.left, rect.bottom-rect.top, TRUE);
and then just resize your OpenGL viewport settings.
If you want to set the display mode too, use this:
// change display mode if destination mode is fullscreen
if (fullscreen) {
DEVMODE dm;
dm.dmSize = sizeof(DEVMODE);
dm.dmPelsWidth = width;
dm.dmPelsHeight = height;
dm.dmBitsPerPel = bitsPerPixel;
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
success = ChangeDisplaySettings(&dm, 0) == DISP_CHANGE_SUCCESSFUL;
}
// reset display mode if destination mode is windowed
if (!fullscreen)
success = ChangeDisplaySettings(0, 0) == DISP_CHANGE_SUCCESSFUL;
Here's the code I use, which uses SetWindowPos() rather than MoveWindow(), as discussed in the comments of the other answer.
void enter_fullscreen(application* App)
{
POINT Point = {0};
HMONITOR Monitor = MonitorFromPoint(Point, MONITOR_DEFAULTTONEAREST);
MONITORINFO MonitorInfo = { sizeof(MonitorInfo) };
if (GetMonitorInfo(Monitor, &MonitorInfo)) {
DWORD Style = WS_POPUP | WS_VISIBLE;
SetWindowLongPtr(App->Window, GWL_STYLE, Style);
SetWindowPos(App->Window, 0, MonitorInfo.rcMonitor.left, MonitorInfo.rcMonitor.top,
MonitorInfo.rcMonitor.right - MonitorInfo.rcMonitor.left, MonitorInfo.rcMonitor.bottom - MonitorInfo.rcMonitor.top,
SWP_FRAMECHANGED | SWP_SHOWWINDOW);
}
App->IsFullscreen = true;
}
void exit_fullscreen(application* App)
{
bool WasMaximized = App->IsMaximized;
DWORD Style = WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN;
if (WasMaximized) {
Style = Style | WS_MAXIMIZE;
}
ivec2 WindowPosition = WasMaximized ? App->WindowPosition : App->NormalWindowPosition;
ivec2 WindowSize = WasMaximized ? App->WindowSize : App->NormalWindowSize;
SetWindowLongPtr(App->Window, GWL_STYLE, Style);
SetWindowPos(App->Window, 0,
WindowPosition.X, WindowPosition.Y, WindowSize.X, WindowSize.Y,
SWP_FRAMECHANGED | SWP_SHOWWINDOW);
App->IsFullscreen = false;
}
I call it on F11, but also on WM_ACTIVATE. Otherwise the window would sometimes keep rendering on top on Windows 7, even if another application would receive all messages, including mouse and keyboard.
I have a rather complex series of applications which depend on the ability to switch applications in the foreground.
My problem is, every 5 or 6 times of switching the applications in the foreground, it simply fails to bring the application forward. GetLastError does not report any issues. Often times I see the correct application flash in the foreground for a moment then the previous application is visible.
I have a Manager application which I have source for, it spawns and controls about 4 applications which I do not have source for. one of the applications it spawns/controls is also a manager which spawns/controls about 5 applications.
This is a sort of kiosk design so the user wont even have a keyboard or mouse, just a touch screen.
I have tried every combination of the Win32 calls to control them I am just out of ideas.
My first attempt was:
SetWindowPos(hApp, HWND_TOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);
SetWindowPos(hApp, HWND_NOTOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);
My second attempt was:
SetForegroundWindow(hApp);
SetActiveWindow(hApp);
SetFocus(hApp);
my third attempt:
DWORD dwThreadID = GetWindowThreadProcessId(hApp, NULL);
AttachThreadInput( dwThreadID, GetCurrentThreadId(), true);
SetForegroundWindow(hApp);
SetActiveWindow(hApp);
SetFocus(hApp);
AttachThreadInput( dwThreadID, GetCurrentThreadId(), false);
my forth attempt:
DWORD dwThreadID = GetWindowThreadProcessId(hApp, NULL);
AttachThreadInput( dwThreadID, GetCurrentThreadId(), true);
SetWindowPos(hApp, HWND_TOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);
SetWindowPos(hApp, HWND_NOTOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);
SetForegroundWindow(hApp);
SetActiveWindow(hApp);
SetFocus(hApp);
AttachThreadInput( dwThreadID, GetCurrentThreadId(), false);
I feel like I am missing an important gotcha when it comes to window switching. I know that only the foreground process can switch windows around but as my main Manager program is spawning and starting all the other processes which I need to control, I feel like it should be capable of moving these windows around. Any suggestions or advice is appreciated.
I was having the same issue and I didn't want to mess up with threads. On experimenting I observed a simple hack to make SetForegroundWindow() work in the expected manner. Here is what I did:
Minimize the window if its not already minimized
Restore the minimized window
Call SetForegroundWindow(), and your window will be on top
Your AttachThreadInput() hack is (I think) a known way to defeat the focus stealing counter-measures in Windows. You are using the wrong handle though, you want to attach to the thread that currently has the focus. Which won't be hApp, you wouldn't need this code otherwise.
Use GetForegroundWindow() to get the handle to the window with the focus.
AttachThreadInput(
GetWindowThreadProcessId(GetForegroundWindow(), NULL),
GetCurrentThreadId(), TRUE
);
Although I think the 2nd argument needs to be thread ID of hApp. Because you don't want to shove your own window if I understood correctly. Not sure if that can work.
The easiest solution in C# to bring a window in the foreground:
Once you have the handle for the window, you can simply call:
SetWindowPos(handle, new IntPtr(0), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
ShowWindow(handle, 5);
SetForegroundWindow(handle);
// If it is minimized, show the window
if (IsIconic(handle))
{
ShowWindow(handle, 3);
}
where
const int SWP_NOMOVE = 0x0002;
const int SWP_NOSIZE = 0x0001;
const int SWP_SHOWWINDOW = 0x0040;
Some windows are locked with setforeground(...),
you need to unlock them. This sequence is useful with any window:
HWND needTopWindow=FindWindow(TEXT("classname"), TEXT("window name"));
the classname and window name you can retrieve with ranorexspy from e.g.
nanoware.cz
if(!::IsWindow(needTopWindow)) return;
BYTE keyState[256] = {0};
//to unlock SetForegroundWindow we need to imitate Alt pressing
if(::GetKeyboardState((LPBYTE)&keyState))
{
if(!(keyState[VK_MENU] & 0x80))
{
::keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
}
}
::SetForegroundWindow(needTopWindow);
if(::GetKeyboardState((LPBYTE)&keyState))
{
if(!(keyState[VK_MENU] & 0x80))
{
::keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
}
DWORD dwThreadID = GetWindowThreadProcessId(needTopWindow, NULL);
AttachThreadInput( dwThreadID, GetCurrentThreadId(), true);
SetWindowPos(needTopWindow, HWND_TOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);
SetWindowPos(needTopWindow, HWND_NOTOPMOST, NULL, NULL, NULL, NULL, SWP_NOMOVE | SWP_NOSIZE);
SetForegroundWindow(needTopWindow);
SetActiveWindow(needTopWindow);
SetFocus(needTopWindow);
AttachThreadInput( dwThreadID, GetCurrentThreadId(), false);
We had a similar problem a couple of years ago. We could solve it by the following function call:
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, SPIF_UPDATEINIFILE);
Give it a try. See the documentation here.
Try pushing the other application windows to the background first.
Also its a bit strange that you use SetWindowPos (SWP) to push a window to the foreground then push it out of the forgreound before using SetForegroundWindow to bring it back foward. Personally I've always used the SWP method without any issue ... but I've always pushed the other windows to the bottom as well.
You also need to consider the chances of window being minimized. If the window or various application are minimized then SetForegroundWindow(hApp) won't work. To be safe use ShowWindow(hApp, 9); I prefer value 9. Have a look at its documentation and choose which you find fit for you.
how to make title bar less window in mfc by code?
Use:
ModifyStyle (WS_CAPTION, 0); // to hide
ModifyStyle (0, WS_CAPTION); // to show
To remove it earlier Override PreCreateWindow() and remove WS_SYSMENU
Just to add, calling:
SetWindowPos(nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER);
after ModifyStyle() applies the settings (at least for dialog-based applications).