How to clone an icon - windows

In Windows, given a handle to an icon (HICON), how do you clone it?
e.g.
HICON CloneIcon(HICON OriginalIcon)
{
ICON clone;
//...
return clone;
}

Use the Win32 API function DuplicateIcon:
HICON CloneIcon(HICON OriginalIcon)
{
return DuplicateIcon(NULL, OriginalIcon); //first parameter is unused
}

Here's the Delphi code to clone an icon.
function CloneIcon(ico: HICON): HICON;
var
info: ICONINFO;
bm: BITMAP;
cx, cy: Integer;
begin
//Get the icon's info (e.g. its bitmap)
GetIconInfo(ico, {var}info);
//Get the bitmap info associated with the icon's color bitmap
GetObject(info.hbmColor, sizeof(bm), #bm);
//Copy the actual icon, now that we know its width and height
Result := CopyImage(ico, IMAGE_ICON, bm.bmWidth, bm.bmHeight, 0);
DeleteObject(info.hbmColor);
DeleteObject(info.hbmMask);
end;
And transcoding to a C/C#-style language in my head:
HICON CloneIcon(HICON ico)
{
ICONINFO info;
//Get the icon's info (e.g. its bitmap)
GetIconInfo(ico, ref info);
//Get the bitmap info associated with the icon's color bitmap
BITMAP bm;
GetObject(info.hbmColor, sizeof(bm), &bm));
//Copy the actual icon, now that we know its width and height
HICON result = CopyImage(ico, IMAGE_ICON, bm.bmWidth, bm.bmHeight, 0);
DeleteObject(info.hbmColor);
DeleteObject(info.hbmMask);
return result;
}
Note: Any code released into public domain. No attribution required.

Related

How to create Rounded Rectangle Buttons in MFC

I need to create Rounded Rectangle Buttons in MFC. I tried several resources but did not found the correct way of explanation. Even in **Code Project ** I founded circular or elliptical buttons.
Please suggest how we can create Rounded Rectangle Buttons or any other article
My answers are...
1. Use Skin Library.
I usually use Codejock SkinFramework.
That's ver easy. Include XTSkinFrameworkPro.h in your stdafx.h then load skin file before your dialog is invoked.
XTPSkinManager()->LoadSkin(_T("..."));
2-1. Draw by yourself.
Most simple one is here. Read it first.
https://vcpptips.wordpress.com/tag/owner-draw-button-control/
Then use this code for making round button. It would be nicer if you slide the label text 1px to right-bottom when they hit the button.
http://www.codeproject.com/Articles/11683/CRoundButton-A-fancy-graphical-button
2-2. Draw by yourself. (Use bitmap)
The other one is using bitmap button. Make a bitmap image of rounded button then set it to your button.
how to add bitmap image to buttons in MFC?
Exsample:
Save below as a SimpleBitmapButton.h and include it in your project.
#pragma once
#include <afxwin.h>
class CSimpleBitmapButton : public CButton
{
DECLARE_DYNAMIC(CSimpleBitmapButton)
protected:
enum EButtonState
{
NORMAL = 0,
PUSHED = 1
};
public:
CSimpleBitmapButton();
BOOL Open( int resource_id );
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
protected:
DECLARE_MESSAGE_MAP()
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
protected:
int Width, Height;
BOOL Pushed;
CBitmap Bitmap;
};
Save below as a SimpleBitmapButton.cpp and include it in your project.
#include "stdafx.h"
#include "SimpleBitmapButton.h"
const int BUTTON_IMAGE_NUM = 2;
IMPLEMENT_DYNAMIC(CSimpleBitmapButton, CButton)
BEGIN_MESSAGE_MAP(CSimpleBitmapButton, CButton)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_CREATE()
END_MESSAGE_MAP()
CSimpleBitmapButton :: CSimpleBitmapButton()
{
Pushed = FALSE;
Width = 0;
Height = 0;
}
void CSimpleBitmapButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct )
{
CDC memDC;
memDC.CreateCompatibleDC( NULL );
CBitmap *oldBitmap = memDC.SelectObject( &Bitmap );
if( Pushed == FALSE )
BitBlt( lpDrawItemStruct->hDC, 0, 0, Width, Height, memDC, 0, 0, SRCCOPY );
else
BitBlt( lpDrawItemStruct->hDC, 0, 0, Width, Height, memDC, Width , 0, SRCCOPY );
memDC.SelectObject( oldBitmap );
}
BOOL CSimpleBitmapButton :: Open( int resource_id )
{
Pushed = FALSE;
Bitmap.LoadBitmap( resource_id );
//adjust the button size
BITMAP bm;
Bitmap.GetObject(sizeof(BITMAP),&bm);
Width = bm.bmWidth / BUTTON_IMAGE_NUM;
Height = bm.bmHeight;
RECT rect;
GetWindowRect( &rect );
GetParent()->ScreenToClient( &rect );
rect.right = rect.left + Width;
rect.bottom = rect.top + Height;
MoveWindow( &rect );
return TRUE;
}
void CSimpleBitmapButton::OnLButtonDown(UINT nFlags, CPoint point)
{
Pushed = TRUE;
Invalidate( FALSE );
CButton::OnLButtonDown(nFlags, point);
}
void CSimpleBitmapButton::OnLButtonUp(UINT nFlags, CPoint point)
{
Pushed = FALSE;
Invalidate( FALSE );
CButton::OnLButtonUp(nFlags, point);
}
Import this bitmap to resource.
Then set IDB_ROUND_BUTTON for resource ID.
Add button on your dialog and set the "Owner Darw" proerty to True. Important!
Add member variables of the button as m_PlayButton.
At the dialog header, include SimpleBitmapButton.h and change the class of m_PlayButton from CButton to CSimpleBitmapButton.
CSimpleBitmapButton m_Button; // it was CButton m_Button;
At the last, set the bitmap on OnInitDialog()
m_PlayButton.Open( IDB_ROUND_BUTTON );

Convert ICON to HBITMAP to be displayed in popup menu?

I'm trying to add bitmaps to a popup menu.
The problem I have is that I create my bitmaps from ICONs dynamically, and I have problems for 24bit color icons vs 24+alpha (32bit) color icons.
It seems that the bitmaps are only always drawn correctly when they are in 32bpp (including alpha channel).
Here's my (test) code:
void ConvertIconToBitmap(CBitmap& bmpObj, HICON hIcon, int cx, int cy, BOOL useDIB) {
CClientDC screenDC(NULL);
CBitmap bmpTmp;
HANDLE_API_FAILURE( bmpTmp.CreateCompatibleBitmap(&screenDC, cx, cy) );
CDC memDC;
HANDLE_API_FAILURE( memDC.CreateCompatibleDC(&screenDC) );
CBitmap* pOldBmp = memDC.SelectObject(&bmpTmp);
HANDLE_API_FAILURE( ::DrawIconEx( memDC.GetSafeHdc(), 0, 0, hIcon, cx, cy, 0, NULL, DI_NORMAL) );
memDC.SelectObject( pOldBmp );
HBITMAP hDibBmp = (HBITMAP)::CopyImage((HANDLE)(HBITMAP)bmpTmp, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
HANDLE_API_FAILURE( hDibBmp );
if (useDIB) {
HANDLE_API_FAILURE( bmpObj.Attach(hDibBmp) ); // works for 32bit/transparanecy
} else {
HANDLE_API_FAILURE( bmpObj.Attach(bmpTmp.Detach()) ); // works for 24bit
}
}
...
CMenu menu;
menu.LoadMenu(IDR_POPUPMENU);
CMenu* pMenu = menu.GetSubMenu(0);
int cx, cy;
cx = cy = GetSystemMetrics(SM_CYMENU);
MENUITEMINFO mii;
mii.cbSize = sizeof mii;
mii.fMask = MIIM_BITMAP;
HICON pwdIco = ExtractIcon(NULL/*=current instance*/, L"path/to/file.exe", 0);
// If icon is 32bit-alpha this works, but doesn't work with 24bit icon
CBitmap bmpTop;
ConvertIconToBitmap(bmpTop, pwdIco, cx, cy, TRUE);
mii.hbmpItem = bmpTop;
pMenu->SetMenuItemInfo(ID_MENU_TOP, &mii, FALSE);
// If icon is 32bit-alpha transparent areas are shown in black, but 24bit icon is also displayed correctly
CBitmap bmpApp;
ConvertIconToBitmap(bmpApp, pwdIco, cx, cy, FALSE);
HBITMAP bmpTransp = bmpApp;
mii.hbmpItem = bmpTransp;
pMenu->SetMenuItemInfo(ID_MENU_TEST, &mii, FALSE);
this->ClientToScreen(&point);
pMenu->TrackPopupMenu(nFlags, point.x, point.y, this);
Since I need to dynamically populate the menu entries images from existing file's icons, I can't just statically fiddle out the bitmaps and use these instead of icons.
What are the requirements for the HBITMAP passed in the hbmpItem member of the MENUITEMINFO structure passed to SetMenuItemInfo ???
And how do I make sure the bitmap "created" with DrawIconEx does fulfill these requirements?
Oh, and to my great pleasure I just learned that 32-bit alpha-blended menu item bitmaps don't work at under Windows XP (transparent=black there), so I'll have to map transparency myself somehow it seems. (Possibly by replacing some color with GetSysColor(COLOR_MENU).)

Get a HBITMAP from an 24bit BMP file loaded into memory

I have a 24bit BMP file loaded into RAM and I'm trying to create a HBITMAP for this image file. I have found some examples around which I've been experimenting with, but can't seem to make work. Basically, I need a HBITMAP for the file, so that I can unload the file and just keep the HBITMAP which I can dispose of later with DeleteObject(). Since this bitmap is loaded very early on in my application, there is no application Window and therefore no HDC. This is what I have so far:-
HBITMAP cBitmap; // This should be where my bitmap handle ends up.
mem; // This is a void* pointer to the loaded BMP file
tagBITMAPFILEHEADER bfh = *(tagBITMAPFILEHEADER*)mem;
tagBITMAPINFOHEADER bih = *(tagBITMAPINFOHEADER*)(mem + sizeof(tagBITMAPFILEHEADER));
RGBQUAD rgb = *(RGBQUAD*)(mem + sizeof(tagBITMAPFILEHEADER) + sizeof(tagBITMAPINFOHEADER));
BITMAPINFO bi;
bi.bmiColors[0] = rgb;
bi.bmiHeader = bih;
UINT8* pixels = mem + bfh.bfOffBits;
void* ppv;
HBITMAP hBitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &ppv, NULL, 0);
SetDIBits(NULL, hBitmap, 0, bih.biHeight, pixels, &bi, DIB_RGB_COLORS);
GetObject(hBitmap, sizeof(BITMAP), &cBitmap);
For some reason that just baffles me, cBitmap ends up being NULL. And another thing that puzzles me... DIB_RGB_COLORS means that the BITMAPINFO has a pointer to literal RGB values, but how does that work with a 24bit image, which doesn't have a palette?
If you are loading a file from disk, it's probably easiest to use LoadImage() with the LR_LOADFROMFILE flag.
To create a HBITMAP from file data that has already been loaded into memory, you can do something similar to the following:
HBITMAP ConvertDibToHBitmap(void* bmpData)
{
HBITMAP hBitmap = NULL;
BOOL success = FALSE;
// NOTE: Assumes the BITMAPFILEHEADER is present (not normally the case for
// an in-memory DIB)
LPBITMAPFILEHEADER bfh = (LPBITMAPFILEHEADER) bmpData;
LPBITMAPINFOHEADER bih = (LPBITMAPINFOHEADER) (bfh + 1);
void *pixels = (char*) (bih + 1); // NOTE: Assumes no color table (i.e., bpp >= 24)
HDC hdc = GetDC(NULL);
if (hdc != NULL) {
hBitmap = CreateCompatibleBitmap(hdc, bih->biWidth, bih->biHeight);
if (hBitmap != NULL) {
HDC hdcMem = CreateCompatibleDC(hdc);
if (hdcMem != NULL) {
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBitmap);
if (StretchDIBits(hdcMem, 0, 0, bih->biWidth, bih->biHeight,
0, 0, bih->biWidth, bih->biHeight, pixels,
(LPBITMAPINFO) bih, DIB_RGB_COLORS, SRCCOPY) > 0)
success = TRUE;
SelectObject(hdcMem, hOldBitmap);
DeleteDC(hdcMem);
}
}
ReleaseDC(NULL, hdc);
}
if (!success && hBitmap != NULL) {
DeleteObject(hBitmap);
hBitmap = NULL;
}
return hBitmap;
}
Um, that's not how GetObject works. The usage is
GetObject(handle, sizeof(object), &object);
In your case, the expectation is that you call it as
BITMAP bitmap;
GetObject(hBitmap, sizeof(BITMAP), &bitmap);
You are not passing a pointer to a BITMAP structure, so the behavior is undefined.
You don't need GetObject at all. You already have your HBITMAP. It's in the hBitmap variable.
cBitmap = hBitmap;

OpenGL - render directly to bitmap

I am making an application that has a bunch of small windows and controls in it (2D rendering), and I would like to render each window and control to its own bitmap. This is what have so far:
uses dglOpenGL;
...
var BMP: TBitmap;
DC, RC: HDC;
...
function TMainForm.Init: Boolean;
begin
Result := InitOpenGL;
if Result = True then
begin
BMP := TBitmap.Create;
BMP.PixelFormat := pf24bit;
BMP.Width := 1280;
BMP.Height := 1024;
DC := (BMP.Canvas.Handle);
RC := CreateRenderingContext(DC,
[opGDI, opDoubleBuffered], // tried changing, didn't help
24,
24,
0,
0,
0,
0);
ActivateRenderingContext(DC, RC);
glClearColor(0.27, 0.4, 0.7, 0.0); // light blue
glViewport(0, 0, 1280, 1024);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
glOrtho(0, 1280, 0, 1024, -1, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
end;
end;
Rendering procedure:
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
// red quad
glColor3f(1, 0, 0);
glBegin(GL_QUADS);
glVertex2f(100, 100);
glVertex2f(1280-100, 100);
glVertex2f(1280-100, 1024-100);
glVertex2f(100, 1024-100);
glend;
// swap
SwapBuffers(DC);
But there is no output.
If I use MainForm.Canvas.Draw(0, 0, BMP); then a white rectangle will appear.
I want to do rendering stuff on bitmaps because I can do a lot of things with bitmaps (draw other images, paint text, blur), but if there another way to do off-screen render then it's okay...
So how do I set up my application for off-screen rendering?
OpenGL contexts must be created matching the target device context. For windows they're created in a different way than for bitmaps. See
http://msdn.microsoft.com/en-us/library/windows/desktop/dd368826(v=vs.85).aspx notably the dwFlags, where there are among others
PFD_DRAW_TO_WINDOW The buffer can draw to a window or device surface.
PFD_DRAW_TO_BITMAP The buffer can draw to a memory bitmap.
However you shouldn rush ahead and create a render context for your DIB DC. Why? Because it will be slow as hell, as OpenGL render contexts on a DIB section will use a software rasterizer supporting only OpenGL-1.1 running on the CPU.
Instead you should create a Framebuffer Object, attach a color renderbuffer attachment and when finished to a glReadPixels into your DIBSection. Much easier, much faster.
Update due to comment request
(I have no idea why StackOverflow doesn't get the syntax coloring right, i.e. figuring out where's a comment and where not)
// flushes the OpenGL error queue and
// counts the total number of errors
int flushGLErrors(void)
{
int i = 0;
while( glGetError() != GL_NO_ERROR ) {
i++;
}
return i;
}
// returns a HBITMAP or NULL.
// The HBITMAP must be freed using DeleteObject
HBITMAP ReadPixelsToHBITMAP(
int x,
int y,
int width,
int height )
{
void *pdata = NULL;
/* Note that this values only makes sense if we know a target
* output size like if we put the image to paper. */
const int physical_resolution = 2835; /* 72 DPI */
BITMAPINFOHEADER bmih = {
/* .biSize = */ sizeof(bmih),
/* .biWidth = */ width,
/* .bi.Height = */ height,
/* .biPlanes = */ 1, /* mandatory */
/* .biBitCount = */ 24, /* 8 bits per pixel */
/* .biCompression = */ BI_RGB, /* uncompressed */
/* .biSizeImage = */ 0, /* implicit */
/* .biXPelsPerMeter = */ physical_resolution, /* ignored */
/* .biYPelsPerMeter = */ physical_resolution, /* ignored */
/* .biClrUsed = */ 0, /* no palette */
/* .biClrImportant = */ 0
};
HBITMAP hbm = CreateDIBSection(
hdc, /* may be different than the DC used for OpenGL */
(PBITMAPINFO)&bmih, /* can do this cast, because no palette is used */
DIB_RGB_COLORS,
&pdata,
NULL,
0
);
if( !hbm ) {
return NULL;
}
flushGLErrors();
glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE);
glPixelStorei(GL_PACK_LSB_FIRST, GL_TRUE);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
if( glGetError() != GL_NO_ERROR ) {
DeleteObject(hbm);
return NULL;
}
glReadPixels(x, y, width, height, GL_BGR, GL_UNSIGNED_BYTE, pdata);
if( glGetError() != GL_NO_ERROR ) {
DeleteObject(hbm);
return NULL;
}
return hbm;
}

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