• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 758
  • Last Modified:

Windows Messages (WM_)

I switched some things from global values to global pointers in my program.  When I did this, my two command buttons used
no longer reacted to BN_CLICKED.  However, they do act upon 52685.  My question is how can I find out what this 56285 is?
I do not want to go about using this if it is perhaps not going to work how I think.
0
List244
Asked:
List244
  • 10
  • 8
1 Solution
 
jkrCommented:
>>My question is how can I find out what this 56285 is?

That is '0xCDCD' in hexadecimal and usually indicates that you are using an uninitialized pointer ('0xCDCD' is the "no man's land" filler that VC++ uses to mark unused areas)
0
 
List244Author Commented:
I pretty much have this:

switch (Message)
{
      case WM_COMMAND:
      switch (WParam)
      {
            case BN_CLICKED:
            //Now Ignored.
            break;
            case 52685:
            //Called on button click
            break;
      }
}

So, why would my having pointers break it from catching BN_Clicked and have it catch at 52685 instead?
All my pointers, only 4 are dynamically allocated before the window is even created, and they are all
assigned value before the CALLBACK function is reached.
0
 
jkrCommented:
Could you post more of your code?
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
List244Author Commented:
Here are the relevant parts:

LRESULT CALLBACK MsgHandler(HWND, UINT, WPARAM, LPARAM);

HWND *NewGame;
HWND *CompChoice;

TTT *Game;
bool *CompPlay;

int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR kposzArgs, int nWinMode)
{
      NewGame = new HWND;
      CompChoice = new HWND;
      Game = new TTT();
      CompPlay = new bool;
      *CompPlay = true;
      HWND Window = CreateWindow("TicTacToe","TicTacToe",WS_CAPTION | WS_SYSMENU |WS_OVERLAPPED,CX,CY,TWidth,THeight,HWND_DESKTOP,NULL,hThisInst,NULL);
      *NewGame = CreateWindowEx(0,"Button","New Game",WS_CHILD | WS_VISIBLE,0,300,150,18,Window,(HMENU)*NewGame,hThisInst,NULL);
      *CompChoice = CreateWindowEx(0,"Button","Human Player 2",WS_CHILD | WS_VISIBLE,151,300,148,18,Window,(HMENU)*CompChoice,hThisInst,NULL);
      ShowWindow(Window,1);
      UpdateWindow(Window);
      while (GetMessage (&RMSG,NULL,0,0))
      {
            TranslateMessage (&RMSG);
            DispatchMessage (&RMSG);
      }
}

Then the part previously posted.   The only changes made however, are that my public variables are now pointers
as opposed to normal globals.  And the program is fully working with the new catch of 52685 but I am not too comfortable
with leaving that as it just doesn't seem right.

0
 
jkrCommented:
Actually, the WindowProc (where you're using that 'switch' statement) would be the part of intrerest.
0
 
List244Author Commented:
LRESULT CALLBACK MsgHandler(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
{
      switch (Message)
      {
            case WM_DESTROY:
                  DestroyWindow(*NewGame);
                  DestroyWindow(*CompChoice);
                  DestroyWindow(Window);
                  if (NewGame !=NULL) //WM calls more than once due to destroying windows, don't delete more than once
                  {
                        delete NewGame;
                        NewGame = NULL;
                        delete CompChoice;
                        delete CompPlay;
                        delete Game;
                  }
                  PostQuitMessage(0);
                  break;
            case WM_PAINT:
                  Draw(&Window);
                  return DefWindowProc(Window, Message, WParam, LParam); //Normal paint too
                  break;
            case WM_COMMAND:
                  switch (WParam)
                  {
                        case BN_CLICKED:
                              if (HWND(LParam) == *NewGame)
                              {
                                    //never called
                              }
                              if (HWND(LParam) == *CompChoice)
                              {
                                    //never called
                              }
                              break;
                        case 52685:
                              if (HWND(LParam) == *NewGame)
                              {
                                    //calls
                              }
                              if (HWND(LParam) == *CompChoice)
                              {
                                    //calls
                              }
                              break;
                  }
            default:
                  return DefWindowProc(Window, Message, WParam, LParam);
                  break;
      }
      return 0;
}

All of that looks good to me, and again nothing has changed other than I now am using pointers.
0
 
jkrCommented:
Ah,

          case WM_COMMAND:
               switch (WParam)
               {

should be

          case WM_COMMAND:
               switch (HIWORD(WParam))
               {
0
 
jkrCommented:
To elaborate - from the docs:

WM_COMMAND
The WM_COMMAND message is sent when the user selects a command item from a menu, when a control sends a notification message to its parent window, or when an accelerator keystroke is translated.

WM_COMMAND
wNotifyCode = HIWORD(wParam); // notification code
wID = LOWORD(wParam);         // item, control, or accelerator identifier
hwndCtl = (HWND) lParam;      // handle of control
 
So, 56285 is the lower word set to '0xCDCD' to indicate that it is not used. 'BN_CLICKED' itself is

#define BN_CLICKED          0
0
 
List244Author Commented:
Okay, that is interesting, so why is it that without pointers, either HIWORD(WParam) or WParam work,yet
with pointers, only HIWORD(WParam) works?
0
 
jkrCommented:
You aren't using any pointers in the WindowProc, there's probably something else going wrong.
0
 
List244Author Commented:
But, if I take my project, and change ONLY the fact that I use pointers.. It fixes/breaks this.

For example, I change it like so:

HWND NewGame;
HWND CompChoice;

TTT Game;
bool CompPlay;
...

int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR kposzArgs, int nWinMode)
{
      CompPlay = true;
        ...
      HWND Window = CreateWindow("TicTacToe","TicTacToe",WS_CAPTION | WS_SYSMENU |WS_OVERLAPPED,CX,CY,TWidth,THeight,HWND_DESKTOP,NULL,hThisInst,NULL);
      NewGame = CreateWindowEx(0,"Button","New Game",WS_CHILD | WS_VISIBLE,0,300,150,18,Window,(HMENU)NewGame,hThisInst,NULL);
      CompChoice = CreateWindowEx(0,"Button","Human Player 2",WS_CHILD | WS_VISIBLE,151,300,148,18,Window,(HMENU)CompChoice,hThisInst,NULL);
        ...
}

LRESULT CALLBACK MsgHandler(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
{
      ...
      case WM_DESTROY:
            DestroyWindow(NewGame);
            DestroyWindow(CompChoice);
            DestroyWindow(Window);
            PostQuitMessage(0);
            break;
      ...
      case WM_COMMAND:
            switch (WParam)
            {
                  case BN_CLICKED:
                  //works
                  ...
            {
      ...
}
0
 
jkrCommented:
Actually, I am not sure why you are using pointers there anyway, since not using them would be the better choice. Also, since these are only fragments, chances are that the problem lies elsewhere. Anyway, without the 'HIWORD()', the code should yield incorrect results. Oh, BTW, did you sitch between Debug and Release?
0
 
List244Author Commented:
Okay, I have tested this these things out.  It seems that in release mode, it works fine with either HIWORD
or not, yet debug only works with HIWORD.  Why would this be?

Also, what is wrong with using pointers for this?
0
 
jkrCommented:
>> It seems that in release mode, it works fine with either HIWORD
>>or not, yet debug only works with HIWORD.  Why would this be?

Because the variables are initialized differently in each build. Release is optimised and will not do any error checking, so the whole wParam value will probably be 0 - so that 'BN_CLICKED' will be recognized incorrectly. In Debug, the unused part of wParam' is set to '0xCDCD', so that invalid access to the lower word can be detected and what caused your app to misbehave.

>>Also, what is wrong with using pointers for this?

It's not wrong, but also not necessary. A HWND is only a scalar 4-byte value, so that you're just adding overhead. That would be like

int* p1 = new int;
int* p2 = new int;

*p1 = 1;
*p2 = 2;

int result = *p1 * *p2;

delete p1;
delete p2;
0
 
List244Author Commented:
Well, I am in a C++ class. I am currently working on a project for the class.  My project is supposed
to demonstrate the use of pointers, dynamically allocated memory, and structures.  This seemed a
little to simple to me, and I figured I would more benefit from a more advanced project.  So I chose
to do a TicTacToe class.  This began as a Console application, however, it really was not looking good
at all.  So I took my completed class and decided to shell it with the Windows API.  However, upon doing
this I still needed to fill the requirements.  I have dynamically created arrays in my class, and structures
too, however it was lacking a bit of pointer notation.  So I decided to switch over my globals to pointers
to show that I have learned to utilize pointers, in order to fit the requirements.  That is when this problem
occurred.  So that can explain to you why I am using pointers.

One thing I am still confused about however, is why when I do not use pointers, and use regular WParam
in debug mode, it works.




Take a look at this:

#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#include <windows.h>

#define TWidth 306
#define THeight 345

LRESULT CALLBACK MsgHandler(HWND, UINT, WPARAM, LPARAM);

HWND NewGame;
HWND CompChoice;

void Draw(HWND *Window);

int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR kposzArgs, int nWinMode)
{
      MSG RMSG;
      WNDCLASSEX WReg;
      WReg.cbSize = sizeof(WNDCLASSEX);
      WReg.cbClsExtra = 0;
      WReg.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);;
      WReg.hCursor = LoadCursor (NULL,IDC_ARROW);
      WReg.hIcon = LoadIcon (NULL,IDI_APPLICATION);
      WReg.hIconSm = LoadIcon(NULL,IDI_WINLOGO);
      WReg.lpszMenuName = NULL;
      WReg.hInstance = hThisInst;
      WReg.lpfnWndProc = MsgHandler;
      WReg.cbWndExtra =0;
      WReg.lpszClassName = "TicTacToe";
      WReg.style = 0;
      if(!RegisterClassEx(&WReg)) { return 0; }
      RECT MRECT;
      GetWindowRect(GetDesktopWindow(),&MRECT);
      int CX = (MRECT.right /2) - (TWidth/2);
      int CY = (MRECT.bottom/2)- (THeight/2);
      HWND Window = CreateWindow("TicTacToe","TicTacToe",WS_CAPTION | WS_SYSMENU |WS_OVERLAPPED,CX,CY,TWidth,THeight,HWND_DESKTOP,NULL,hThisInst,NULL);
      NewGame = CreateWindowEx(0,"Button","New Game",WS_CHILD | WS_VISIBLE,0,300,150,18,Window,(HMENU)NewGame,hThisInst,NULL);
      CompChoice = CreateWindowEx(0,"Button","Human Player 2",WS_CHILD | WS_VISIBLE,151,300,148,18,Window,(HMENU)CompChoice,hThisInst,NULL);
      ShowWindow(Window,1);
      UpdateWindow(Window);
      while (GetMessage (&RMSG,NULL,0,0))
      {
            TranslateMessage (&RMSG);
            DispatchMessage (&RMSG);
      }
      return RMSG.wParam;
}


LRESULT CALLBACK MsgHandler(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
{
      switch (Message)
      {
            case WM_DESTROY:
                  DestroyWindow(NewGame);
                  DestroyWindow(CompChoice);
                  DestroyWindow(Window);
                  PostQuitMessage(0);
                  break;
            case WM_COMMAND:
                  switch (WParam)  //Works fine
                  {
                        case BN_CLICKED:
                              if (HWND(LParam) == NewGame)
                              {
                                    MessageBox(Window,"NewGame Pressed","NGP",MB_OK);
                              }
                              if (HWND(LParam) == CompChoice)
                              {
                                    MessageBox(Window,"Other Pressed","OP",MB_OK);
                              }
                              break;
                  }
            default:
                  return DefWindowProc(Window, Message, WParam, LParam);
                  break;
      }
      return 0;
}

Either HIWORD or not, this will function correctly.  Yet you make NewGame and CompChoice pointers, and make the
necessary changes, dereferencing and deletion, it will no longer work as WParam.  ::









#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#include <windows.h>

#define TWidth 306
#define THeight 345

LRESULT CALLBACK MsgHandler(HWND, UINT, WPARAM, LPARAM);

HWND *NewGame;
HWND *CompChoice;

void Draw(HWND *Window);

int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR kposzArgs, int nWinMode)
{
      NewGame = new HWND;
      CompChoice = new HWND;
      MSG RMSG;
      WNDCLASSEX WReg;
      WReg.cbSize = sizeof(WNDCLASSEX);
      WReg.cbClsExtra = 0;
      WReg.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);;
      WReg.hCursor = LoadCursor (NULL,IDC_ARROW);
      WReg.hIcon = LoadIcon (NULL,IDI_APPLICATION);
      WReg.hIconSm = LoadIcon(NULL,IDI_WINLOGO);
      WReg.lpszMenuName = NULL;
      WReg.hInstance = hThisInst;
      WReg.lpfnWndProc = MsgHandler;
      WReg.cbWndExtra =0;
      WReg.lpszClassName = "TicTacToe";
      WReg.style = 0;
      if(!RegisterClassEx(&WReg)) { return 0; }
      RECT MRECT;
      GetWindowRect(GetDesktopWindow(),&MRECT);
      int CX = (MRECT.right /2) - (TWidth/2);
      int CY = (MRECT.bottom/2)- (THeight/2);
      HWND Window = CreateWindow("TicTacToe","TicTacToe",WS_CAPTION | WS_SYSMENU |WS_OVERLAPPED,CX,CY,TWidth,THeight,HWND_DESKTOP,NULL,hThisInst,NULL);
      *NewGame = CreateWindowEx(0,"Button","New Game",WS_CHILD | WS_VISIBLE,0,300,150,18,Window,(HMENU)*NewGame,hThisInst,NULL);
      *CompChoice = CreateWindowEx(0,"Button","Human Player 2",WS_CHILD | WS_VISIBLE,151,300,148,18,Window,(HMENU)*CompChoice,hThisInst,NULL);
      ShowWindow(Window,1);
      UpdateWindow(Window);
      while (GetMessage (&RMSG,NULL,0,0))
      {
            TranslateMessage (&RMSG);
            DispatchMessage (&RMSG);
      }
      return RMSG.wParam;
}


LRESULT CALLBACK MsgHandler(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
{
      switch (Message)
      {
            case WM_DESTROY:
                  DestroyWindow(*NewGame);
                  DestroyWindow(*CompChoice);
                  DestroyWindow(Window);
                  if (NewGame !=NULL)
                  {
                        delete NewGame;
                        NewGame = NULL;
                        delete CompChoice;
                  }
                  PostQuitMessage(0);
                  break;
            case WM_COMMAND:
                  switch (WParam)  ///NEEDS TO BE HIWORD
                  {
                        case BN_CLICKED:
                              if (HWND(LParam) == *NewGame)
                              {
                                    MessageBox(Window,"NewGame Pressed","NGP",MB_OK);
                              }
                              if (HWND(LParam) == *CompChoice)
                              {
                                    MessageBox(Window,"Other Pressed","OP",MB_OK);
                              }
                              break;
                  }
            default:
                  return DefWindowProc(Window, Message, WParam, LParam);
                  break;
      }
      return 0;
}

Between the two you will notice the only difference is the pointer notation.
0
 
jkrCommented:
That's indeed odd, tried both and they work as you stated. Anyway, if you want to handle other button messages than 'BN_CLICKED' in the future, you'll need to use 'HIWORD()'.
0
 
List244Author Commented:
Haha, alright, well that is good to know, and quite odd.  At any rate, you answered my question, and HIWORD
did fix the pointers, so I will go ahead and accept, but if you ever find and answer to why this works how it does
with the pointers, drop a message by here, I'd love to know what is going on there. Thanks for the help.
0
 
jkrCommented:
Just as a side note: The different value is a control ID

wID = LOWORD(wParam);         // item, control, or accelerator identifier

and - in case of a dialog would contain the control ID of the button.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 10
  • 8
Tackle projects and never again get stuck behind a technical roadblock.
Join Now