Sign in to follow this  
Khatharr

[C++/Win32] - Having trouble understanding how controls work with messages

Recommended Posts

Here's my code:

#include <windows.h>
#include <commctrl.h>
#include <stdio.h>

#define IDC_SLIDER1 101
#define IDC_PROGRESS1 102
#define IDC_BUTTON1 103

const char g_szClassName[] = "myWindowClass";
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
HFONT hfont0;
HWND hCtrl0_0, hCtrl0_1, hCtrl0_2;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
//create and register window class
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(wc));
wc.cbSize = sizeof(wc);
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(0, (LPCTSTR)IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = g_szClassName;
if(!RegisterClassEx(&wc)) {MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0;}

//populate window with controls
hfont0 = CreateFont(-11, 0, 0, 0, 400, FALSE, FALSE, FALSE, 0, 400, 2, 1, 1, ("Microsoft Sans Serif"));
HWND hwnd = CreateWindowEx(WS_EX_APPWINDOW, g_szClassName, "Controls Test", WS_OVERLAPPEDWINDOW, 200, 200, 306, 123, 0, 0, hInstance, 0);
hCtrl0_0 = CreateWindowEx(0, TRACKBAR_CLASS, 0, WS_VISIBLE | WS_CHILD | WS_TABSTOP | TBS_BOTH | TBS_NOTICKS, 3, 36, 294, 26, hwnd, (HMENU)IDC_SLIDER1, hInstance, 0);
SendMessage(hCtrl0_0, WM_SETFONT, (WPARAM)hfont0, FALSE);
SendMessage(hCtrl0_0, TBM_SETRANGE, FALSE, MAKELONG(1, 100));
SendMessage(hCtrl0_0, TBM_SETPOS, FALSE, 1);
hCtrl0_1 = CreateWindowEx(0, PROGRESS_CLASS, 0, WS_VISIBLE | WS_CHILD, 3, 5, 294, 20, hwnd, (HMENU)IDC_PROGRESS1, hInstance, 0);
SendMessage(hCtrl0_1, WM_SETFONT, (WPARAM)hfont0, FALSE);
SendMessage(hCtrl0_0, PBM_SETRANGE, FALSE, MAKELONG(1, 100));
hCtrl0_2 = CreateWindowEx(0, WC_BUTTON, ("OK"), WS_VISIBLE | WS_CHILD | WS_TABSTOP | 0x00000001, 105, 68, 90, 23, hwnd, (HMENU)IDC_BUTTON1, hInstance, 0);
SendMessage(hCtrl0_2, WM_SETFONT, (WPARAM)hfont0, FALSE);

//start 'er up and run the control loop
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
MSG Msg;
while(GetMessage(&Msg, NULL, 0, 0) > 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
unsigned int pos;
switch(msg) {
case BN_CLICKED: break; //this never gets triggered for some reason
case TB_ENDTRACK: //this isn't working correctly
pos = SendMessage(hCtrl0_0, TBM_GETPOS, NULL, NULL);
SendMessage(hCtrl0_1, PBM_SETPOS, pos, NULL);
break;
case WM_CLOSE: DestroyWindow(hwnd); break;
case WM_DESTROY: PostQuitMessage(0); break;
default: return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}


I'm running into some problems. What I want it to do is set the progress bar according to the value of the slider and quit the app when the OK button is pressed. I've tried using TB_THUMBTRACK rather than TB_ENDTRACK but that doesn't seem to work either. The progress bar only seems to set itself when I first touch the slider and then stops responding. The BN_CLICKED message never gets recieved by the proc.

When I looked over the definitions for the messages I saw that a lot of controls could potentially send the same message, so I'm pretty sure I'm missing something here. Can anyone tell me why this isn't working and what I'm missing here???

Thanks in advance for any advice. :)

Share this post


Link to post
Share on other sites

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

unsigned int pos;

switch(msg) {

case WM_COMMAND:
switch(wParam)
{
//Do control stuff here!
}
break;

case WM_CLOSE:
DestroyWindow(hwnd);
break;

case WM_DESTROY:
PostQuitMessage(0);
break;

default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;

}



However, I'm not sure how to handle those BN_ and TB_ messages. But you MUST put them into the switch(WM_COMMAND).

WM_COMMAND gets sent when a controls wants something from you.

Share this post


Link to post
Share on other sites
I'll check out WM_COMMAND on MSDN and see if it explains where to put the message type.

---------------------------------------

Looks like HIWORD(wParam) is the message sent from the control and LOWORD(wParam) is the id number of the control. I've got the button working now, and the this seems better conceptually but the slider still isn't doing what I want. I'll fiddle with it a little more. Thank you again!

[Edited by - Khatharr on September 25, 2010 10:28:23 PM]

Share this post


Link to post
Share on other sites
A slider (track bar) sends its notification messages via either WM_HSCROLL or WM_VSCROLL. Look those messages up in MSDN and you'll get nice sample code.

And, even more important: MOVE THE CALL TO DEFWINDOWPROC AFTER THE SWITCH, NOT AS DEFAULT CASE. For most messages you want to pass the messages on to get handled properly.

Share this post


Link to post
Share on other sites
Okay, I've got it working now. Still one or two things with the trackbar that seem needlessly complex so I didn't go into them, but I learned what I was looking for and I know where the other info can be found.

Thanks for the help, you guys. And yeah, I restructured my proc when I started walking through it in my head. I tried it with WM_HSCROLL but it was producing strange results that would end up making the bar reset to zero whenever I wasn't moving it, so I went with WM_NOTIFY. Apparently a trackbar will send a notification message whenever its value is being changed, so I just set it up so that whenever a notification is recieved from the trackbar it updates the progress bar with the current trackbar position.

Here's the code I ended up with. Nothing exciting, but still:
#include <windows.h>
#include <commctrl.h>

#define IDC_SLIDER1 101
#define IDC_PROGRESS1 102
#define IDC_BUTTON1 103

const char g_szClassName[] = "myWindowClass";
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
HFONT hfont0;
HWND hCtrl0_0, hCtrl0_1, hCtrl0_2;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
//create and register window class
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(wc));
wc.cbSize = sizeof(wc);
wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(0, (LPCTSTR)IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = g_szClassName;
if(!RegisterClassEx(&wc)) {MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0;}

//populate window with controls
hfont0 = CreateFont(-11, 0, 0, 0, 400, FALSE, FALSE, FALSE, 0, 400, 2, 1, 1, ("Microsoft Sans Serif"));
HWND hwnd = CreateWindowEx(WS_EX_APPWINDOW, g_szClassName, "Controls Test", WS_OVERLAPPEDWINDOW, 200, 200, 306, 123, 0, 0, hInstance, 0);
hCtrl0_0 = CreateWindowEx(0, TRACKBAR_CLASS, 0, WS_VISIBLE|WS_CHILD|WS_TABSTOP|TBS_BOTH|TBS_NOTICKS, 3, 36, 294, 26, hwnd, (HMENU)IDC_SLIDER1, hInstance, 0);
SendMessage(hCtrl0_0, WM_SETFONT, (WPARAM)hfont0, FALSE);
SendMessage(hCtrl0_0, TBM_SETRANGE, FALSE, MAKELONG(0, 100));
SendMessage(hCtrl0_0, TBM_SETPOS, FALSE, 0);
hCtrl0_1 = CreateWindowEx(0, PROGRESS_CLASS, 0, WS_VISIBLE|WS_CHILD|PBS_SMOOTH, 3, 5, 294, 20, hwnd, (HMENU)IDC_PROGRESS1, hInstance, 0);
SendMessage(hCtrl0_1, WM_SETFONT, (WPARAM)hfont0, FALSE);
SendMessage(hCtrl0_0, PBM_SETRANGE, FALSE, MAKELONG(0, 100));
hCtrl0_2 = CreateWindowEx(0, WC_BUTTON, ("OK"), WS_VISIBLE|WS_CHILD|WS_TABSTOP|0x00000001, 105, 68, 90, 23, hwnd, (HMENU)IDC_BUTTON1, hInstance, 0);
SendMessage(hCtrl0_2, WM_SETFONT, (WPARAM)hfont0, FALSE);

//start 'er up and run the control loop
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
MSG Msg;
while(GetMessage(&Msg, NULL, 0, 0) > 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
unsigned pos;
switch(msg) {
case WM_NOTIFY:
if(wParam == IDC_SLIDER1) {
pos = SendMessage(hCtrl0_0, TBM_GETPOS, NULL, NULL);
SendMessage(hCtrl0_1, PBM_SETPOS, pos, NULL);
return 1;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
case WM_COMMAND:
if((LOWORD(wParam) == IDC_BUTTON1) && (HIWORD(wParam) == BN_CLICKED)) {
PostQuitMessage(0);
return 1;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this