I was wondering how can I create a window using Win32 API with a specific client area size.
When trying to create a window using the following piece of code, the entire window is 640x480, with the window's chrome taking some of the client area:
HWND hWnd;
WNDCLASSEX WndClsEx;
ZeroMemory(&WndClsEx, sizeof(WNDCLASSEX));
WndClsEx.cbSize = sizeof(WNDCLASSEX);
WndClsEx.style = CS_HREDRAW | CS_VREDRAW;
WndClsEx.lpfnWndProc = DefWindowProc;
WndClsEx.cbClsExtra = 0;
WndClsEx.cbWndExtra = 0;
WndClsEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClsEx.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClsEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
WndClsEx.lpszMenuName = NULL;
WndClsEx.lpszClassName = TEXT("Title");
WndClsEx.hInstance = hInstance;
WndClsEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&WndClsEx);
hWnd = CreateWindowEx( NULL,
TEXT("Title"),
TEXT("Title"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
NULL,
NULL,
hInstance,
NULL);
Assuming simple math won't quite solve the problem, how do I take the chrome size into account?
Note: I'm using SDL after creating the window, but I'm guessing it's bound to the window size and makes no difference to its size.
You can use the AdjustWindowRect or AdjustWindowRectEx function to calculate the window size given a desired client area size.
Related
When I create a window with CreateWindowEx it will follow the resolution but also use the scale settings from the display settings. So, in 1920 x 1080 if I try to create the window, the size is actually 1200 something when scale is at 150%. Is there a way to get around this limitation? If I just set the size manually to 1920 x 1080 I get a cropped window. Thanks.
auto activeWindow = GetActiveWindow();
HMONITOR monitor = MonitorFromWindow(activeWindow, MONITOR_DEFAULTTONEAREST);
//
// Get the logical width and height of the monitor
MONITORINFOEX monitorInfoEx;
monitorInfoEx.cbSize = sizeof(monitorInfoEx);
GetMonitorInfo(monitor, &monitorInfoEx);
auto cxLogical = monitorInfoEx.rcMonitor.right - monitorInfoEx.rcMonitor.left;
auto cyLogical = monitorInfoEx.rcMonitor.bottom - monitorInfoEx.rcMonitor.top;
vScreenSize = { cxLogical, cyLogical };
WNDCLASS wc;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.hInstance = GetModuleHandle(nullptr);
wc.lpfnWndProc = olc_WindowEvent;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.lpszMenuName = nullptr;
wc.hbrBackground = nullptr;
wc.lpszClassName = olcT("Wusik SQ480 Engine");
RegisterClass(&wc);
DWORD dwExStyle = 0;
DWORD dwStyle = WS_VISIBLE | WS_POPUP;
olc::vi2d vTopLeft = vWindowPos;
// Keep client size as requested
RECT rWndRect = { 0, 0, vWindowSize.x, vWindowSize.y };
AdjustWindowRectEx(&rWndRect, dwStyle, FALSE, dwExStyle);
int width = rWndRect.right - rWndRect.left;
int height = rWndRect.bottom - rWndRect.top;
olc_hWnd = CreateWindowEx(dwExStyle, olcT("Wusik SQ480 Engine"), olcT(""), dwStyle,
vTopLeft.x, vTopLeft.y, width, height, NULL, NULL, GetModuleHandle(nullptr), this);
Thanks to Remy Lebeau it was as simple as adding the following call to the main initialization of the app. Now I always get a window with the physical resolution and not a logic scaled resolution.
SetProcessDPIAware();
I have a problem with setting the titlebar icon for my application.
I have been trying to figure this out, Googling what is wrong, for 2 days already, without any success.
MainWindow.cpp:
#include "../../res/Icons.h"
void MainWindow::Create(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
const wchar_t CLASS_NAME[] = L"MainWindow";
WNDCLASSEX wc = {};
wc.cbSize = sizeof(wc);
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
wc.hIcon = LoadIcon(NULL,IDI_MYICON);
wc.hIconSm = LoadIcon(NULL,IDI_MYICON);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = CreateSolidBrush(RGB(255,255,255));
RegisterClassEx(&wc);
HWND hwnd = CreateWindowEx(0, CLASS_NAME, wstring(Language::wText[1].begin(),Language::wText[1].end()).c_str(), WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Icons.h
#define IDI_MYICON 1000
Icons.rc
IDI_MYICON ICON "App.ico"
It compiles fine, and the icon is shown in the Taskbar, as well as in the executable file, but not in the titlebar. The icon is a standard ico with dimensions of 32x32. I have even tried using LoadImage(), but same result.
You are passing NULL to LoadIcon, you should pass the HINSTANCE of your application to load from your own resources.
The resource header file needs to be used in conjunction with the .rc file (i.e. #include "icon. h" in icon. rc), otherwise the specific icon file (path is specified in the .rc file) will not be found. In addition, if "icon.h" does not end with an empty line, you will get an unexpected end of file found error.
I am writing a C/C++ windows app which calls CreateWindow as follows:
HWND hWnd = CreateWindow(pszClassName, title_.c_str(), WS_OVERLAPPED | WS_VISIBLE | WS_POPUP | WS_SIZEBOX, 50, 50, 400, 100, NULL, NULL, hInst, this);
Nothing particularly complex about it, however, it is appearing on every desktop on my computer when I switch from one desktop to another with CTRL-WIN < or >.
How do you make window you create in an app remain only on the desktop that you created it on?
I am compiling this app in 64bit and running it on Windows 10.
Code:
Global:
WNDCLASSEX wc;
Window procedure:
case WM_KEYDOWN:
if(wParam == VK_F11)
{
wc.style = HWND_DESKTOP;//The window is child
//of desktop
}
break;
WinMain:
LPCSTR windowName = "Answer on StackOwerflow";
MSG messages;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "The classname";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
wc.lpszClassName,
windowName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
ShowWindow(hWnd);
UpdateWindow(hWnd);
while(GetMessage(&messages, NULL, 0, 0) > 0)
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return 0;
I'm trying to add a child window to my main window, but the function CreatWindow is throwing an exception saying that can't access address at 0x00000, but it works fine when I try to create a button, I tracked the variables and none of them are null, here it is:
WNDCLASSEX windowClass;
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.hInstance = hInstance;
windowClass.lpfnWndProc = NULL;
windowClass.lpszClassName = className;
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.lpszMenuName = NULL;
if (!RegisterClassEx(&windowClass)){
return;
}
window = CreateWindowEx(0,
className,
(LPCTSTR)NULL,
WS_CHILD | WS_BORDER,
0, 0, 0, 0,
owner,
(HMENU)ID,
hInstance,
NULL);
the code above giving the error, the important variables come from here:
gl = new OpenGLContainer("hellogl", hInstance);
addChild(gl);
the first parameter is the className, the constructor only performs an attribution, the addChild method call gl->setOwner(window_handler) and gl->create() which is the first piece of code I posted.
I also saw the stack list, and the problem is after the program enter in the CreateWindow function, which is very strange because the debugger shows that none of the values(pointers) are null.
Could it be failing because lpfnWndProc is NULL?
I want to make a popup window appear when I hit a button that is located on the main window of my program. I have looked everywhere for popup window examples, and most answers just showed me how to make a window, buttt I already have a main window in my application.
Basically the difficulty I am having is knowing where to put the new window class and code for my popup window(since I want the pop window to have different properties than my main one). Should it also be in the WinMain function or should it be in one of the cases in the CALLBACK WndProcedure section?
some of the code I have for my window is:
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
I just am not sure where to put it... Should it be placed in the code that is activated when the button is pressed, or should it stay in the WinMain function, together with the information of the other window?
I hope you can understand my predicament, I am somewhat new to programming.
Register window at main() together with main window. And in case statement of WndProc call CreateWindowEx().
But I don't know how make animation of popup. I can imagine that code should put somewhere in the WM_CREATE, but this I don't know.
if you mean just another window for example window for settings you should use DialogBoxes.
P.S. If you are russian, then I strongly recommend the book "Win32 API. Effective Application Development" by Yuri Shchupak on russian
The new window should be created in the case statement in your wndProc that handles the button click.