Can I make a Win32 child window show under the parent window? - windows

I want to add a child window to a parent window,make the content of child window is below the parent window(Z order).just like compose two layer,not replacement.Because I want some UI element in parent window can be seen within the child window's area,but not cover all of the child window.The child window should be a window,so I can't just using parent window's UI system to implement the child window's UI.
Is there any api to achieve this?
I found something like "UpdateLayeredWindow",But I failed to create a layer child window,CreateWindowEx return NULL and GetLastError return 0.This code was copy from Windows's example.and the demo project (DirectCompositionLayeredChildWindow) works well.
HRESULT hr = S_OK;
// Register the window class.
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH));
wc.lpszClassName = L"DirectComposition Window Class";
RegisterClassEx(&wc);
// Creates the m_hMainWindow window.
HWND m_hMainWindow = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW| WS_EX_COMPOSITED, // Extended window style
wc.lpszClassName, // Name of window class
L"DirectComposition Layered Child Window Sample", // Title-bar string
WS_OVERLAPPED | WS_SYSMENU, // Top-level window
CW_USEDEFAULT, // Horizontal position
CW_USEDEFAULT, // Vertical position
1000, // Width
700, // Height
NULL, // Parent
NULL, // Class menu
GetModuleHandle(NULL), // Handle to application instance
NULL // Window-creation data
);
if (!m_hMainWindow)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
if (SUCCEEDED(hr))
{
ShowWindow(m_hMainWindow, SW_SHOWDEFAULT);
}
WNDCLASSEX wcex = { 0 };
wcex.cbSize = sizeof(wcex);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WindowProc;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszClassName = L"DirectCompositionChildWindow-Child";
RegisterClassEx(&wcex);
// !!! m_hControlChildWindow is always NULL
HWND m_hControlChildWindow = CreateWindowEx(WS_EX_LAYERED, // Extended window style
wcex.lpszClassName, // Name of window class
NULL, // Title-bar string
WS_CHILD, // Child window
30,30, 100, 100, // Window will be resized via MoveWindow
m_hMainWindow, // Parent
NULL, // Class menu
GetModuleHandle(NULL), // Handle to application instance
NULL); // Window-creation data
if (!m_hControlChildWindow)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
ShowWindow(m_hControlChildWindow, nCmdShow);
UpdateWindow(m_hControlChildWindow);

This cannot be done, as explained here:
No part of a child window ever appears outside the borders of its parent window.
Also:
A child window is grouped with its parent in z-order.
In other words: You cannot create a child window that's either outside the parent window's client area, or underneath the parent window in Z-order.

Related

Why Windows is not giving me a window the size I asked?

I'm trying to create a window with the client size the same as the display resolution (1366 x 768).
For this, I'm using AdjustWindowRectEx to get the calculated width and height of the window to be created.
The first red circle in the top right is the actual display resolution that I want the client size of the window to have.
The second red circle is the width and height that AdjustWindowRectEx calculated the window to be created with (client size + borders and title bar).
The last red circle in the bottom is the actual client size that I got after the window has been created.
The height is not what I ask Windows to give me. I asked 768 and I got 749.
Is there some limit height the window can be created with? No matter how much I ask the height to be, it never give me more than 749.
Thanks!
In CreateWindow(), WM_GETMINMAXINFO information will be sent to confirm the size of the current form can be generated, you can refer to MINMAXINFO to view its specific structure. If the size of the created form is larger than its default setting, it will be overwritten by the default size. So it will be smaller than the size you set when it is created.
According to the WM_GETMINMAXINFO:
An application can override the defaults by setting the members of MINMAXINFO, and return zero if an application processes this message.
Here is the sample:
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT,WPARAM,LPARAM);
static int max_right, max_bottom;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("hello windows");
HWND hwnd = 0;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
}
DEVMODEW display_mode;
if (EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &display_mode))
{
DWORD window_style = WS_CAPTION | WS_MINIMIZE | WS_SYSMENU | WS_VISIBLE;
RECT window_rect;
window_rect.right = display_mode.dmPelsWidth;
window_rect.bottom = display_mode.dmPelsHeight;
window_rect.left = window_rect.top = 0;
AdjustWindowRectEx(&window_rect, window_style, FALSE, 0);
max_right = window_rect.right - window_rect.left;
max_bottom = window_rect.bottom - window_rect.top;
HWND window_handle = CreateWindowEx(0, wndclass.lpszClassName,
TEXT("the hello program"),
window_style,
CW_USEDEFAULT, CW_USEDEFAULT,
max_right,
max_bottom,
NULL, NULL, hInstance, NULL);
ShowWindow(window_handle, iCmdShow);
UpdateWindow(window_handle);
if (window_handle)
{
RECT client_rect;
GetClientRect(window_handle, &client_rect);
}
}
while (GetMessageW(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch (message)
{
case WM_CREATE:
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
EndPaint(hwnd, &ps);
return 0;
case WM_GETMINMAXINFO:
((MINMAXINFO*)lParam)->ptMaxSize = { max_right,max_bottom };
((MINMAXINFO*)lParam)->ptMaxTrackSize = { max_right,max_bottom };
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
Use function GetSystemMetrics(...).
This function calculate size(resolution) of screen.
For X and Y coordinate, see my example to set variables(use in CreateWindowEx, where set a width and height of window.)Example:
int x = GetSystemMetrics(SM_CXSCREEN);
int y = GetSystemMetrics(SM_CYSCREEN);

How to create a window in secondary monitor in win10 app

I am very new to the win10 dev, and I am trying to create a win10 app which will create a floating window in all the monitors the system is connected to. So far I am successful in using GDI API to create window in my primary monitor, but it is not working on my secondary monitor, I cannot get why it is not working even when I am using the API as mentioned in the microsoft page.
Below is my code
// Register the window class.
WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = DXGIDraw::WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR);
wcex.hInstance = HINST_THISCOMPONENT;
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.hCursor = LoadCursor(NULL, IDI_APPLICATION);
wcex.lpszClassName = L"DemoApp";
RegisterClassEx(&wcex);
m_hwnd = CreateWindowEx(WS_EX_LAYERED,
L"DemoApp",
L"Demo App",
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
HWND_DESKTOP,
NULL,
HINST_THISCOMPONENT,
NULL
);
const int nWidth = GetSystemMetrics(SM_CXSCREEN);
const int nHeight = GetSystemMetrics(SM_CYSCREEN);
CImage img;
DISPLAY_DEVICE ddd;
ZeroMemory(&ddd, sizeof(ddd));
ddd.cb = sizeof(ddd);
for (int i = 0; EnumDisplayDevices(NULL, i, &ddd, 0); i++)
{
if (ddd.StateFlags & DISPLAY_DEVICE_ACTIVE) {
//Active monitor
}
if (ddd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
//Primary monitor
}
else {
//other types
}
}
//The following API supposed to work for all the monitors, but this API is not working. This is where I need attention.
HDC hdcScreen = CreateDC(ddd.DeviceName, NULL, NULL, NULL);
//But if I use below API I can get it working for the primary monitor only, still trying to understand why
//HDC hdcScreen = CreateDC(L"DISPLAY", NULL, NULL, NULL);
HDC hDC = CreateCompatibleDC(hdcScreen);
HBITMAP hBmp = CreateCompatibleBitmap(hdcScreen, nWidth, nHeight);
HBITMAP hBmpOld = (HBITMAP)SelectObject(hDC, hBmp);
img.Draw(hDC, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight);
//Add layered window
BLENDFUNCTION blend = { 0 };
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
POINT ptLocation = { 0, 0 };
SIZE szWnd = { nWidth, nHeight };
POINT ptSrc = { 0, 0 };
BOOL status1 = UpdateLayeredWindow(m_hwnd, hdcScreen, &ptLocation, &szWnd, hDC, &ptSrc, 0, &blend, ULW_ALPHA);
//Set window's position
BOOL status = SetWindowPos(m_hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
hr = m_hwnd ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
{
BOOL status;
status = ShowWindow(m_hwnd, SW_MAXIMIZE);
status = UpdateWindow(m_hwnd);
}
SelectObject(hDC, hBmpOld);
DeleteObject(hBmp);
DeleteDC(hDC);
ReleaseDC(NULL, hdcScreen);
}
EnumDisplayDevices is the wrong API for this job. You need to use EnumDisplayMonitors which gives you the monitor coordinates directly.
You need to retreive the bounding rectangle for the desired monitor within the virtual screen, and then you can position a window within that rectangle as desired. Use EnumDisplayMonitors() to get the rectangle of each moinitor. Or, if you have an HMONITOR handle to a specific monitor, you can use GetMonitorInfo().

How can I drag a transparent window without leaving edge traces in Win32 API?

I am trying to create a transparent window using Win32 API which can be dragged across the screen and the window's background will keep on being transparent and showing the windows behind it.
I'm doing so by performing the following:
ATOM MyRegisterClass(HINSTANCE hInstance){
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = NULL;
return RegisterClassEx(&wcex);}
The: wcex.hbrBackground = NULL; line is responsible of making the window transparent upon initialization.
Creating the window is done in:
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow){
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;}
And the way the window keeps on being transparent upon dragging is:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_MOVING:
InvalidateRect(hWnd, NULL, TRUE);
break;
default:
return = DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;}
Where the:
InvalidateRect(hWnd, NULL, TRUE);
line causes the window to be redrawn upon moving event.
The problem is that the background of the window is not re-rendered in the regions which are not "new".
Example in words,
Say I open an application (word, chrome etc. - lets call it WindowB) and than I run my application which opens WindowA that covers WindowB but I can see the content of WindowB in the background (since WindowA is a transparent window). If I drag WindowA across the screen I still see WindowB in the background and that's great.
If I minimize WindowB I still see portion of WindowB which intersects WindowA region (No problem here since I didn't redraw WindowA).
If I start to drag WindowA, I assumed that WindowB portion showed in WindowA will disappear and I'll see what's currently is the top most window in the desktop as WindowA's background, since I call InvalidateRect(hWnd, NULL, TRUE); upon the moving event.
What actually happens is that I still see WindowB in all the regions which are not "new regions" - by new regions I mean regions in the screen where WindowA was moved to and was not part of WindowA region before the move.
It seems that the call for InvalidateRect(hWnd, NULL, TRUE); is not enough since it renders only "new regions".
A snapshot to illustrate the issue can be found in the following link:
http://imgur.com/gallery/2uVX4yj/new
I would very much appreciate any assistance on this issue.
The main function of my application is the default function created by Visual Studio 2010 for a Win32 Application project:
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow){
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TEST2, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TEST2));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;}

WinApi -> How to create a ComboBox (without resources)

Can anyone tell me how to create a ComboBox with a DropDownList (like the C# ComboBox Control with DropDownStyle = DropDownList) without resources and without MFC? I googled around 20 minutes but all codessamples I found created strange Controls for me (for example a plain area with a checkbox which cant be checked...). My code looks like this:
WNDCLASSEX wcex;
HWND hwnd;
HWND button;
HDC hDC;
HGLRC hRC;
MSG msg;
BOOL bQuit = FALSE;
float theta = 0.0f;
/* register window class */
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_OWNDC;
wcex.lpfnWndProc = WindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "GLSample";
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);;
if (!RegisterClassEx(&wcex))
return 0;
/* create main window */
hwnd = CreateWindowEx(0,
"GLSample",
"OpenGL Sample",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
256,
256,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, nCmdShow);
button = CreateWindow("GLSample", "knopf", WS_CHILD | WS_VISIBLE, 200, 200, 150, 60, hwnd, NULL, hInstance, NULL);
You have to call CreateWindow() again, specifying lpClassName = combobox and dwStyle = CBS_DROPDOWNLIST.
You can edit its content by sending messages to it, using SendMessage()

How do I put my OpenGL app into fullscreen mode? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I'm new to OpenGL but I've written a small application that runs fine in a window. Now i'd like to run it fullscreen.
There is this from the FAQ, but it seems to require GLUT, which is not open source. What's a good method for putting an OpenGL app into fullscreen mode? On Windows XP for now, but I'll be porting to other platforms.
Maciek's answer should work. You just need the full source from the NeHe tutorial.
There is much more source involved in taking care of all the little details like resizing the Window to fullscreen, covering up the start bar. Here's the CreateGLWindow function from one of my apps (a near-copy of NeHe's method).
inline BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
GLuint PixelFormat; // Holds The Results After Searching For A Match
HINSTANCE hInstance; // Holds The Instance Of The Application
WNDCLASS wc; // Windows Class Structure
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
WindowRect.left=(long)0; // Set Left Value To 0
WindowRect.right=(long)width; // Set Right Value To Requested Width
WindowRect.top=(long)0; // Set Top Value To 0
WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height
SCREENWIDTH=width;
SCREENHEIGHT=height;
fullscreen=fullscreenflag; // Set The Global Fullscreen Flag
hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For GL
wc.lpszMenuName = NULL; // We Don't Want A Menu
wc.lpszClassName = "OpenGL"; // Set The Class Name
if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (fullscreen) // Attempt Fullscreen Mode?
{
DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
return FALSE; // Return FALSE
}
}
}
if (fullscreen) // Are We Still In Fullscreen Mode?
{
dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
dwStyle=WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; // Windows Style
ShowCursor(FALSE); // Hide Mouse Pointer
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; // Windows Style
}
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size
// Create The Window
if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window
"OpenGL", // Class Name
title, // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
0, 0, // Window Position
WindowRect.right-WindowRect.left, // Calculate Window Width
WindowRect.bottom-WindowRect.top, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL))) // Dont Pass Anything To WM_CREATE
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
bits, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
32, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
ShowWindow(hWnd,SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
SetFocus(hWnd); // Sets Keyboard Focus To The Window
ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen
if (!InitGL()) // Initialize Our Newly Created GL Window
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
return TRUE; // Success
}
This is all included in NeHe Lesson 1.
I'm partial to SDL for OpenGL window mangament and context wrangling.
I'm assuming you're creating the OpenGL window the "hard way" (via win32)
the code below hails from NeHe, the link points to a tutorial containing OpenGL window creation with fullscreen support :
in case your compiler doesn't define CDS_FULLSCREEN, add :
#define CDS_FULLSCREEN 4
at the top of your app.
if (fullscreen)
{
DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options. Quit Or Run In A Window.
if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{(...)
Here is how SDL does it (MS Windows):
// query desktop video settings
DEVMODE SDL_desktop_mode;
EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &SDL_desktop_mode);
settings.dmBitsPerPel = video->format->BitsPerPixel;
settings.dmPelsWidth = width;
settings.dmPelsHeight = height;
settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
// make sure to use monitor frequency that works in fullscreen
if (width <= (int)SDL_desktop_mode.dmPelsWidth &&
height <= (int)SDL_desktop_mode.dmPelsHeight) {
settings.dmDisplayFrequency = SDL_desktop_mode.dmDisplayFrequency;
settings.dmFields |= DM_DISPLAYFREQUENCY;
}
changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
if (! changed && (settings.dmFields & DM_DISPLAYFREQUENCY)) {
settings.dmFields &= ~DM_DISPLAYFREQUENCY;
changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
}
What SDL does when you set fullscreen mode and your target resolution is not the desktop resolution is to make sure you are using the proper monitor frequency for fullscreen mode by simply telling the driver to apply the frequency that the desktop has been using (which runs in fullscreen, so its refresh rate will work with any resolution in fullscreen mode).

Resources