Many people wrote function for centering a window but the function always use the first monitor !
They used GetSystemMetrics but the function use the primary monitor.
I did not made better, because I used SystemParametersInfo which returns results for the first monitor !
The result always was not very pretty.
Today I use an other method.
I consider that I have not two monitors but a virtual monitor.
First Monitor 1366 x 1280 and the 1600 x 1280
So, when I create a window I have a virtual monitor of 2966 x 1280.
If I want to create the window on the first monitor the X coordinate is 0 and if I want to have the window
on the second monitor the X coordinate is bigger than 1366.
Don't forget to store the monitor handle.
#define WIN32_LEAN_AND_MEAN /* speed up compilations */
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <wchar.h>
#include "main.h"
#define NELEMS(a) (sizeof(a) / sizeof((a)[0]))
/** Global variables ********************************************************/
static HINSTANCE hInstance ;
void CenterWindow(HWND __hWnd)
{
HMONITOR _hMonitor ;
MONITORINFO _MonitorInfo ;
RECT _WindowRect ;
int _WindowWidth, _WindowHeight ;
GetWindowRect(__hWnd,&_WindowRect) ;
_WindowWidth = _WindowRect.right - _WindowRect.left ;
_WindowHeight = _WindowRect.bottom - _WindowRect.top ;
_hMonitor = MonitorFromRect(&_WindowRect,MONITOR_DEFAULTTOPRIMARY) ;
_MonitorInfo.cbSize = sizeof(MONITORINFO) ;
GetMonitorInfo(_hMonitor,&_MonitorInfo) ;
_WindowRect.left = _MonitorInfo.rcWork.left + (_MonitorInfo.rcWork.right - _MonitorInfo.rcWork.left - _WindowWidth) / 2 ;
_WindowRect.top = _MonitorInfo.rcWork.top + (_MonitorInfo.rcWork.bottom - _MonitorInfo.rcWork.top - _WindowHeight) / 2 ;
_WindowRect.right = _WindowRect.left + _WindowWidth ;
_WindowRect.bottom = _WindowRect.top + _WindowHeight ;
SetWindowPos(__hWnd,NULL,_WindowRect.left,_WindowRect.top,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE) ;
return ;
}
static LRESULT CALLBACK AboutDlgProc(HWND __hDlg,UINT __uMsg,WPARAM __wParam,LPARAM __lParam)
{
switch(__uMsg)
{
case WM_INITDIALOG :
return (TRUE) ;
case WM_COMMAND :
switch(__wParam)
{
case IDOK :
case IDCANCEL :
EndDialog(__hDlg,TRUE) ;
return (TRUE) ;
}
break ;
}
return (FALSE) ;
}
static void Main_OnPaint(HWND __hWnd)
{
PAINTSTRUCT ps ;
RECT rc ;
BeginPaint(__hWnd,&ps) ;
GetClientRect(__hWnd,&rc) ;
DrawText(ps.hdc,L"Hello,Windows!",-1,&rc,DT_SINGLELINE|DT_CENTER|DT_VCENTER) ;
EndPaint(__hWnd,&ps) ;
return ;
}
static void Main_OnCommand(HWND __hWnd,int id,HWND hwndCtl,UINT codeNotify)
{
switch(id)
{
case IDM_ABOUT:
DialogBox(hInstance,MAKEINTRESOURCE(DLG_ABOUT),__hWnd,(DLGPROC)AboutDlgProc) ;
/* TODO: Enter more commands here */
}
return ;
}
static void Main_OnDestroy(HWND __hWnd)
{
PostQuitMessage(0) ;
return ;
}
static LRESULT CALLBACK MainWndProc(HWND __hWnd,UINT _Msg,WPARAM wParam,LPARAM lParam)
{
switch(_Msg)
{
HANDLE_MSG(__hWnd,WM_PAINT,Main_OnPaint) ;
HANDLE_MSG(__hWnd,WM_COMMAND,Main_OnCommand) ;
HANDLE_MSG(__hWnd,WM_DESTROY,Main_OnDestroy) ;
/* TODO: enter more messages here */
default:
return DefWindowProc(__hWnd,_Msg,wParam,lParam) ;
}
return (0) ;
}
int APIENTRY wWinMain(HINSTANCE __hInstance,HINSTANCE __hPrevInstance,WCHAR *__pszCmdLine,int __nCmdShow)
{
INITCOMMONCONTROLSEX _Icc ;
WNDCLASS _Wc ;
HWND _hWnd ;
MSG _Msg ;
_Wc.hInstance = hInstance = __hInstance ;
_Icc.dwSize = sizeof(_Icc) ;
_Icc.dwICC = ICC_WIN95_CLASSES /*|ICC_COOL_CLASSES|ICC_DATE_CLASSES|ICC_PAGESCROLLER_CLASS|ICC_USEREX_CLASSES|... */ ;
InitCommonControlsEx(&_Icc) ;
/* Register the main window class */
_Wc.lpszClassName = L"MonitorTClass" ;
_Wc.lpfnWndProc = MainWndProc ;
_Wc.style = CS_OWNDC|CS_VREDRAW|CS_HREDRAW|CS_DROPSHADOW ;
_Wc.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDR_ICO_MAIN)) ;
_Wc.hCursor = LoadCursor(NULL,IDC_ARROW) ;
_Wc.hbrBackground =(HBRUSH)(COLOR_WINDOW + 1) ;
_Wc.lpszMenuName = MAKEINTRESOURCE(IDR_MNU_MAIN) ;
_Wc.cbClsExtra = 0 ;
_Wc.cbWndExtra = 0 ;
if(!RegisterClass(&_Wc))
return (1) ;
/* Create the main window */
_hWnd = CreateWindow(L"MonitorTClass",L"MonitorTest Program",WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_VSCROLL,
1500,0,800,600,NULL,NULL,hInstance,NULL) ;
if(!_hWnd) return (1) ;
/* Show and paint the main window */
ShowWindow(_hWnd,__nCmdShow) ;
UpdateWindow(_hWnd) ;
CenterWindow(_hWnd) ;
/* Pump messages until we are done */
while(GetMessage(&_Msg,NULL,0,0) > 0)
{
TranslateMessage(&_Msg) ;
DispatchMessage(&_Msg) ;
}
return (_Msg.wParam) ;
}
I have not invented that but tooke it from
https://docs.microsoft.com/en-us/windows/win32/gdi/positioning-objects-on-a-multiple-display-setup.
If you only have one monitor you can change
_hMonitor = MonitorFromRect(&_WindowRect,MONITOR_DEFAULTTONEAREST) ;
by
_hMonitor = MonitorFromRect(&_WindowRect,MONITOR_DEFAULTTOPRIMARY) ;
I wrote a demonstration program display a window on the second monitor.
The goal is to create a window of 800 x 600.
The X coordinate is 1500.
If there is only one monitor the window is centered on it.
I hope you understood what I wante to do and that it will be useful.