Thanks for the input on this Chris, Jose and Patrice. I do believe I'll 'mend my ways' and start returning the original background mode back into the DC before exiting the WM_PAINT handler. This kind of snuck up on me. I had first learned this function back in Windows 95 days and hadn't really thought much about it since then. The code that doesn't do this I have posted here in the C and C++ section on my board, so I'll fix it.
Actually, what prompted me to go through this code is that I believe I'll finally convert it to 64 bit - a topic that I know is one of your favorites Patrice! I bought Visual Studio 2008 several years back and one of the things I wanted to experiment with was 64 bit compiling with C or C++. Well, that was one big non - event - kind of like the Y2K bug or Mayan Calander Final date plus 1! One selects '64 bit Platform' from a list box, Visual Studio creates a new directory for the 64 bit binary outputs, and that's it. Everything turned out as expected. My primary computer at the time was WinXP 32 bit which however, had a 64 bit processor. Of course, the 64 bit executable wouldn't run on it, although I could use my Visual Studio installation on that computer to create the 64 bit executable. Since then I got a 64 bit Win7 OS, and they run fine on that, of course. But I suppose I'll convert all my code, because sometimes C++ coders wanting to learn SDK use my examples, and lots of folks now want to do 64 bit.
Just taking a quick look at the situation, it looks like the major thing that needs to change is SetWindowLongPtr() instead of SetWindowLong() and GetWindowLongPtr() instead of GetWindowLong(). Also, when allocating WNDCLASSEX::cbWndExtra bytes use something like sizeof(void*) or sizeof(size_t) or sizeof(ptrdiff_t). The variable types really look confusing. I was surprised to see that ints, UINTs, and so on, still retain their 32 bit size. I learned C back in DOS days and the 16 bit int was promoted to 32 bits, somewhat unlike PowerBASIC where INTEGERs remained the same and we used LONGs instead. But for backward compatibility they left ints and a lot of the same stuff alone.
Here is a GUI program similiar to the one I have posted here that displays to its window the dimensions of a box and its volume, that is correct in every way I think (and hope). It compiles and operates correctly with VC++9 and mingw Code::Blocks. CodeBlocks is compiling as 32 bit and VC9 as 64 bit. Note I used an iBkMode variable in the WM_PAINT handler to save and restore whatever was in the DC. Also, it opens an output file where I print that stuff out, along with various variable sizes when running as a 64 bit program. First, here is the output from it ...
Entering WM_CREATE Case!
sizeof(void*) = 8
sizeof(size_t) = 8
sizeof(int) = 4
sizeof(long) = 4
sizeof(UINT) = 4
sizeof(HDC) = 8
sizeof(DWORD32) = 4
sizeof(DWORD64) = 8
sizeof(ptrdiff_t) = 8
pBox = 30304624
OPAQUE = 2
TRANSPARENT = 1
Leaving WM_CREATE Case!
Entering Case WM_PAINT!
iBkMode = 2 (OPAQUE, Which Is Equal To 2, Was Just Taken Out, And TRANSPARENT, Equal To 1, Was Just Put In)
iBkMode = 1 (Now TRANSPARENT, Which Is Equal To 1, Has Just Been Removed, And OPAQUE - The Default, Replaced.
Leaving Case WM_PAINT
Entering WM_DESTROY Case!
pBox = 30304624
Leaving WM_DESTROY Case!
And here's the other necessary code ...
//Main.cpp
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include "CBox.h"
FILE* fp = NULL;
LRESULT CALLBACK WndProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
{
fp=fopen("Output.txt","w");
if(fp)
{
fprintf(fp,"Entering WM_CREATE Case!\n");
fprintf(fp," sizeof(void*) = %d\n",sizeof(void*));
fprintf(fp," sizeof(size_t) = %d\n",sizeof(size_t));
fprintf(fp," sizeof(int) = %d\n",sizeof(int));
fprintf(fp," sizeof(long) = %d\n",sizeof(long));
fprintf(fp," sizeof(UINT) = %d\n",sizeof(UINT));
fprintf(fp," sizeof(HDC) = %d\n",sizeof(HDC));
fprintf(fp," sizeof(DWORD32) = %d\n",sizeof(DWORD32));
fprintf(fp," sizeof(DWORD64) = %d\n",sizeof(DWORD64));
fprintf(fp," sizeof(ptrdiff_t) = %d\n",sizeof(ptrdiff_t));
CBox* pBox=NULL;
pBox=new CBox(2.0,3.0,4.0);
if(pBox)
{
SetWindowLongPtr(hWnd,0,(long)pBox);
fprintf(fp," pBox = %d\n",(int)pBox);
fprintf(fp," OPAQUE = %d\n",OPAQUE);
fprintf(fp," TRANSPARENT = %d\n",TRANSPARENT);
fprintf(fp,"Leaving WM_CREATE Case!\n");
return 0;
}
else
return -1;
}
else
return -1;
}
case WM_PAINT:
{
CBox* pBox=NULL;
HFONT hFont,hTmp;
PAINTSTRUCT ps;
HDC hDC;
TCHAR szBuffer[128];
fprintf(fp,"\nEntering Case WM_PAINT!\n");
hDC=BeginPaint(hWnd,&ps);
int iBkMode=SetBkMode(hDC,TRANSPARENT); // This Is What I Had >> SetBkMode(hDC,TRANSPARENT);
fprintf(fp," iBkMode = %d (OPAQUE, Which Is Equal To 2, Was Just Taken Out, And TRANSPARENT, Equal To 1, Was Just Put In)\n",iBkMode);
hFont=CreateFont(-1*(18*GetDeviceCaps(hDC,LOGPIXELSY))/72,0,0,0,FW_HEAVY,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,DEFAULT_PITCH,_T("Courier New"));
hTmp=(HFONT)SelectObject(hDC,hFont);
pBox=(CBox*)GetWindowLongPtr(hWnd,0);
_stprintf(szBuffer,_T("Box.GetLength() = %6.2f"),pBox->GetLength());
TextOut(hDC,25,30,szBuffer,(int)_tcslen(szBuffer));
_stprintf(szBuffer,_T("Box.GetWidth() = %6.2f"),pBox->GetWidth());
TextOut(hDC,25,60,szBuffer,(int)_tcslen(szBuffer));
_stprintf(szBuffer,_T("Box.GetHeight() = %6.2f"),pBox->GetHeight());
TextOut(hDC,25,90,szBuffer,(int)_tcslen(szBuffer));
_stprintf(szBuffer,_T("Box.Volume() = %6.2f"),pBox->Volume());
TextOut(hDC,25,120,szBuffer,(int)_tcslen(szBuffer));
SelectObject(hDC,hTmp);
DeleteObject(hFont);
iBkMode=SetBkMode(hDC,iBkMode); // I didn't do this before
fprintf(fp," iBkMode = %d (Now TRANSPARENT, Which Is Equal To 1, Has Just Been Removed, And OPAQUE - The Default, Replaced.\n",iBkMode);
EndPaint(hWnd,&ps);
fprintf(fp,"Leaving Case WM_PAINT\n");
return 0;
}
case WM_DESTROY:
{
fprintf(fp,"\nEntering WM_DESTROY Case!\n");
CBox* pBox=NULL;
pBox=(CBox*)GetWindowLongPtr(hWnd,0); //termination.
fprintf(fp," pBox = %d\n",(int)pBox);
if(pBox)
delete pBox;
PostQuitMessage(0);
fprintf(fp,"Leaving WM_DESTROY Case!\n");
fclose(fp);
return 0;
}
}
return (DefWindowProc(hWnd, msg, wParam, lParam));
}
int WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
TCHAR szClassName[]=_T("CBox7");
MSG messages;
WNDCLASS wc;
HWND hWnd;
wc.lpszClassName=szClassName; wc.lpfnWndProc=WndProc;
wc.style=0, wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wc.hInstance=hIns, wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW; wc.cbWndExtra=sizeof(size_t); //sizeof(size_t);
wc.lpszMenuName=NULL; wc.cbClsExtra=0;
RegisterClass(&wc);
hWnd=CreateWindow(szClassName,szClassName,WS_OVERLAPPEDWINDOW^WS_MAXIMIZEBOX,100,100,400,300,0,0,hIns,0);
ShowWindow(hWnd,iShow);
while(GetMessage(&messages,NULL,0,0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return (int)messages.wParam;
}
/*
DWORD32 32-bit unsigned integer
DWORD64 64-bit unsigned integer
INT32 32-bit signed integer
INT64 64-bit signed integer
LONG32 32-bit signed integer
LONG64 64-bit signed integer
UINT32 Unsigned INT32
UINT64 Unsigned INT64
ULONG32 Unsigned LONG32
ULONG64 Unsigned LONG64
DWORD_PTR Unsigned long type for pointer precision.
HALF_PTR Half the size of a pointer. Use within a structure that contains a pointer and two small fields.
INT_PTR Signed integer type for pointer precision.
LONG_PTR Signed long type for pointer precision.
SIZE_T The maximum number of bytes to which a pointer can refer. Use for a count that must span the full range of a pointer.
SSIZE_T Signed SIZE_T.
UHALF_PTR Unsigned HALF_PTR.
UINT_PTR Unsigned INT_PTR.
ULONG_PTR Unsigned LONG_PTR.
Term Description
====================================================================================================================================
POINTER_32 A 32-bit pointer. On 32-bit Windows, this is a native pointer. On 64-bit Windows, this is a truncated 64-bit pointer.
POINTER_64 A 64-bit pointer. On 64-bit Windows, this is a native pointer. On 32-bit Windows, this is a sign-extended 32-bit pointer.
*/
//CBox.h
#ifndef CBox_h
#define CBox_h
class CBox
{
public:
CBox(double,double,double); //Constructor
~CBox(); //Destructor
double GetLength() const; //m_Length accessor
double GetWidth() const; //m_Width accessor
double GetHeight() const; //m_Height accessor
double Volume() const; //Returns Volume() of Box
private:
double m_Length;
double m_Width;
double m_Height;
};
#endif
//CBox.cpp
#include "CBox.h"
CBox::CBox(double dblLength, double dblWidth, double dblHeight)
{
this->m_Length=dblLength;
this->m_Width=dblWidth;
this->m_Height=dblHeight;
}
CBox::~CBox()
{
//destructor
}
double CBox::GetLength() const
{
return this->m_Length;
}
double CBox::GetWidth() const
{
return this->m_Width;
}
double CBox::GetHeight() const
{
return this->m_Height;
}
double CBox::Volume() const
{
return m_Length*m_Width*m_Height;
}
I had to put casts in several places to eliminate warnings from the VC9 compiler. The strangest one was the return from winmain() because WPARAM is now 64 bits! Also strlen() returns 64 bit lengths apparently, but the TextOut() function wants a 32 bit quantity for the length of string to output, so I needed casts there too.