creating controls using API's functions

Pages: 12
i'm trying, for now, build 1 class for create a label(STATIC class).
ok... i'm using the console way(but don't horry is only for test the class's).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <windows.h>

class label
{
private:
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

public:

    label(HWND value)
    {

    HWND hwnd;
    MSG Msg;

    hwnd = CreateWindowEx(
    WS_EX_CLIENTEDGE,
    "STATIC",
    "hello world",
    SS_LEFT|WS_CHILD|WS_VISIBLE,
    30, 30, 100, 100,
    value,
    NULL,
    GetModuleHandle(NULL),
     NULL);

    }
};

in main.cpp:
1
2
3
4
5
6
7
8
9
10
#include "console.h"
#include "variant.h"
#include "label.h"


int main()
{
    label b(GetForegroundWindow());
	return 0;
}

(i'm build my own controls class)
but tell me why the label isn't showed?
i don't get any error, but the label isn't showed :(
The best you can do as far as I know in terms of including a Window Procedure in a class is to leave it out of the class but make it a 'friend'. The reason for this is because every class member function receives the hidden 'this' pointer as the 1st parameter of the method invocation. The Window Procedure, on the other hand, has a very definite and defined function signature, i.e., HWND, UINT, WPARAM, LPARAM. Therefore, it can't be called 'back' into by Windows the Operating System with five parameters, i.e., this, HWND, UINT, WPARAM, LPARAM. That would cause an instant crash.

If that code you posted actually runs without crashing (whether or not it works as expected), I'm guessing the CreateWindowEx() call failed. It certainly is a strange thing to do, but you might get the label to instantiate successfully on a console window if you would set the parent of the label as the console window. I believe there is a Windows Api function to return the handle of the console window. I've used it occasionally. I think its GetConsoleWindow() or something like that.
Last edited on
sorry but the control isn't showed :(
(1st i must see the control, then i must do something for the window procedure that i'm thinking ;) )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <windows.h>
#include <iostream>

class label
{
private:
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

public:

    label(HWND value)
    {

    HWND hwnd;
    MSG Msg;

    hwnd = CreateWindowEx(
    WS_EX_LEFT| WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
    "STATIC",
    "hello world",
    SS_LEFT|WS_CHILD|WS_VISIBLE,
    0, 0, 100, 100,
    value,
    NULL,
    GetModuleHandle(NULL),
     NULL);
    if (hwnd==0) std::cout << "erro";
     ShowWindow(hwnd,SW_SHOW);
    }
};


main.cpp:
1
2
3
4
5
6
7
8
#include "label.h"


int main()
{
    label b(GetConsoleWindow());
	return 0;
}


the label isn't showed :(
i'm testing in windows appilcation and it's showed ;)
now i will rebuild the class.
and i will give news
ok... but i'm doing 1 or 2 things badly :(
i'm trying work with WNDCLASSEX, but seems that i can't... why? because i'm creating a control, using a standard class... so what i need to do for connect the control with label procedure?
(i know that it's possible but i don't know how)
how can i get the handle?

SetWindowLong( GetModuleHandle(NULL), GWL_WNDPROC, &WndProc);
these line is for connect the label with message loop
A windows GUI application is NOT a console app and it does not use main(0 as entry point, instead it uses WinMain.

Use your favorite IDE project wizard to get started.

i did that... now the label is showed. the problem is connect the label with window procedure:
SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)WndProc);
i try search and research, but i can't fix these line... please tell me more
Hey Cambalinho! I actually asked myself this morning how to effectively do this and 12 hours later I feel that I have a pretty good solution for wrapping and abstracting Windows Controls.

Sorry it's long. I wanted to keep as much detail as possible for you.

reference material:
http://blogs.msdn.com/b/oldnewthing/archive/2005/04/22/410773.aspx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
-BaseWindow.h
#pragma once
#include <windows.h>
#include <windowsx.h>
#include <string>

class BaseWindow
{
private:

	void SetID()
	{
		static unsigned int nextID = 1;
		m_id = nextID;
		nextID++;
	}

	static LRESULT CALLBACK s_MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

protected:

	unsigned int	m_id;
	HWND			m_hwnd;
	HINSTANCE		m_appInstance;
	POINT			m_position;
	POINT			m_size;

	std::wstring	m_caption;

	bool			m_fullscreen;
	bool			m_minOrMax;
	bool			m_hasMenu;
	bool			m_isMainWindow;

protected:

	void Register();
	//http://bit.ly/1dGC1uC
	void WinCreateWindowEx(DWORD dwExStyle,
						   LPCWSTR pszName,
						   DWORD dwStyle,
						   int x, int y,
						   int w, int h,
						   HWND hwndParent,
						   HMENU hmenu);

	virtual LRESULT HandleMessage(UINT msg, WPARAM wParam, LPARAM lParam);
	virtual LPCWSTR ClassName() = 0;
	virtual BOOL WinRegisterClass(WNDCLASSEX *wcx)
	{
		return RegisterClassEx(wcx);
	}

public:

	BaseWindow()
	{
		SetID();				//get a unique ID
        //. . .
	}

	~BaseWindow(){}

	//Initalizes all window paramaters and returns a pointer
	virtual int Init(HINSTANCE appInstance, 
					 const wchar_t* caption, 
					 long x, long y, 
					 long w, long h) = 0;

	virtual void Show(BOOL forceForeground = false);
    //. . .
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
-BaseWindow.cpp
//#include "EngineCommonStd.h" //Custom Precompiled Header
#include "BaseWindow.h"

//#include "WindowController.h"
//===============================================

#pragma region Private Definitions

LRESULT CALLBACK BaseWindow::s_MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	BaseWindow *self;

	if (msg == WM_NCCREATE)
	{
		LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
		self = reinterpret_cast<BaseWindow*>(lpcs->lpCreateParams);
		self->m_hwnd = hwnd;

		SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(self));
	}
	else
	{
		self = reinterpret_cast<BaseWindow*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
	}


	if (self)
	{
		return self->HandleMessage(msg, wParam, lParam);
	}
	else
	{
		return DefWindowProc(hwnd, msg, wParam, lParam);
	}
}

#pragma endregion

#pragma region Protected Definitions

void BaseWindow::Register()
{
	WNDCLASSEX wcx;

	wcx.cbSize = sizeof(WNDCLASSEX);
	wcx.style = 0;
	wcx.lpfnWndProc = BaseWindow::s_MsgProc;
	wcx.cbClsExtra = 0;
	wcx.cbWndExtra = 0;
	wcx.hInstance = m_appInstance;
	wcx.hIcon = NULL;
	wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wcx.lpszMenuName = NULL;
	wcx.lpszClassName = ClassName();
	wcx.hIconSm = NULL;

	if (!WinRegisterClass(&wcx))
	{
		DWORD error = GetLastError();
		if (error == ERROR_CLASS_ALREADY_EXISTS)
		{
			ENGINE_WARNING(L"Class already exists\n"
						   L"\tClass: " + std::wstring(ClassName()) + L" ");
		}
		else
		{
			ENGINE_ERROR(L"Failed to register window: " + m_caption + L"\n" +
						L"<Unknown Reason> \n" +
						L"Class: " + ClassName() + L"\n" +
						L"Closing Application.");

			PostQuitMessage(0);
		}
	}
}

void BaseWindow::WinCreateWindowEx(DWORD exStyle, LPCWSTR caption, DWORD style, int x, int y, int w, int h, HWND hwndParent, HMENU menu)
{
	m_caption	= caption;
	m_position	= { x, y };
	m_size		= { w, h };

	RECT R = { 0, 0, w, h };
	AdjustWindowRectEx(&R, style, (menu ? true : false), exStyle);
	m_hwnd = CreateWindowEx(exStyle, ClassName(), 
							caption, 
							style, 
							x, y, 
							R.right, R.bottom, 
							hwndParent, 
							menu, 
							m_appInstance, 
							this);

	if (!m_hwnd)
	{
		DWORD error = GetLastError();
		ENGINE_ERROR(L"Failed to create window: " + m_caption + L"\n" +
					 L"Class: " + ClassName() + L"\n" + 
					 L"Closing Application.");

		PostQuitMessage(0);
	}
}

LRESULT BaseWindow::HandleMessage(UINT msg, WPARAM wParam, LPARAM lParam)
{
	LRESULT lres;

	switch (msg)
	{
	case WM_NCDESTROY:
		lres = DefWindowProc(m_hwnd, msg, wParam, lParam);
		SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0);
		return lres;

	case WM_DESTROY:
		if (m_isMainWindow) PostQuitMessage(0);
		return 0;
	}

	return DefWindowProc(m_hwnd, msg, wParam, lParam);
}

#pragma endregion

//===============================================

#pragma region Public API

//. . .

void BaseWindow::Show(BOOL forceForeground /* = false */)
{
	ShowWindow(m_hwnd, SW_SHOW);

	if (forceForeground)
		SetForegroundWindow(m_hwnd);

	UpdateWindow(m_hwnd);
}

//. . .

#pragma endregion

//=============================================== 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
- RenderWindow.h
#pragma once
#include "BaseWindow.h"

class IRenderDevice;

class RenderWindow : public BaseWindow
{
private:

	IRenderDevice* m_deviceContext;

private:

protected:

	virtual LRESULT HandleMessage(UINT msg, WPARAM wParam, LPARAM lParam);
	virtual LPCWSTR ClassName() { return TEXT("RenderWindow"); }

public:

	virtual int Init(HINSTANCE appInstance,
					 const wchar_t* caption,
					 long x, long y,
					 long w, long h);

	void AttatchDevice(IRenderDevice* device);
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
RenderWindow.cpp
//#include "EngineCommonStd.h" //Custom PCH
#include "RenderWindow.h"

#include "IRenderDevice.h"
/* //Interface Render Device Class - could be OpenGL, DX9, 10, 11
 class IRenderDevice
 {
 friend class RenderWindow;
 private:
 
    RenderWindow*	m_window;
    bool			m_active;
 
 private:
 
    virtual bool InitContext(RenderWindow* targetWindow) = 0;
 
    virtual void ActivateProc(bool active) = 0;
    virtual void SizeProc(int type, int width, int height) = 0;
    virtual void WindowCloseProc() = 0;
    virtual void ExitSizeMoveProc() = 0;
 
 public:
 
    virtual std::wstring DeviceName() = 0;
 };
 */

//This extends the basic functionlity of a BaseWindow to bind
//	relavent Procs with a graphics device
LRESULT RenderWindow::HandleMessage(UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_ACTIVATE:
		if (LOWORD(wParam) == WA_INACTIVE)
			m_deviceContext->ActivateProc(true);
		else
			m_deviceContext->ActivateProc(false);
		return 0;


	case WM_SIZE:
		m_deviceContext->SizeProc(wParam, LOWORD(lParam), HIWORD(lParam));
		return 0;


	case WM_EXITSIZEMOVE:
		m_deviceContext->ExitSizeMoveProc();
		return 0;


	case WM_CLOSE:
		m_deviceContext->WindowCloseProc();
		DestroyWindow(m_hwnd);
		return 0;
	}

	//Call the base functionality definition
	return __super::HandleMessage(msg, wParam, lParam);
}

int RenderWindow::Init(HINSTANCE appInstance,
				 const wchar_t* caption,
				 long x, long y,
				 long w, long h)
{
	//Initalize member variables
	m_appInstance	= appInstance;

	//Register window class
	Register();
    
	//Create window
	WinCreateWindowEx(0, caption,
					WS_OVERLAPPEDWINDOW,
					x, y,
					w, h,
					NULL, NULL);
	
	//Return the unique ID for reference purposes
	return m_id;
}

void RenderWindow::AttatchDevice(IRenderDevice* device)
{
	//Attempt to attatch and form context
	//	with the graphics device
	if (!device->InitContext(this))
	{
        // - Failure message and close app
	}

	//Nothing bad happen. Grab a reference to it and move on
	m_deviceContext = device;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- WinMain.cpp
#include "RenderWindow.h"
#include "D3D9RenderDevice.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
{
	//Allocation
	D3D9RenderDevice* graphics = DBG_NEW D3D9RenderDevice();
	RenderWindow* window = DBG_NEW RenderWindow();

	//Initilization
	graphics->Init(60, true); //Init with update frequency of 60hz and display stats
	window->Init(hInstance, L"My Test App", 50, 50, 800, 600); //location 50, 50. 800x600 dimension

	//Staging
	window->AttatchDevice(graphics); //Attatch device with window to form a Context

	window->Show(); //Show the Window
}
ew, I forgot how much the formatting can get butchered.

If you have any questions don't hesitate to ask! Most of the environment this was done in is my personal engine that I use for testing new stuff. Some code was omitted to satisfy length limitations.
thanks for that code but i realy need ask you something:
- the control is showed and i can change it's propreties;
- but i realy don't understand how i can connect the control with window procedure(that is inside of the class)... that's why i used the SetWindowLong() function. so tell me how can i connect the control with windows procedure?
Ok, I think I understand the issue a little better. But, I'm thinking of two seperate things you might be trying to do.

1: You want to send messages to other controls from a window procedure. All of this is determined before the program is compiled and ran.

2: You want to have a window created then at runtime create another control, a label, and dynamically link it to one of the window's procedure events. Such as WM_ACTIVATE to either enable or disable the control based on the activation state of the primary control window.

Number 2 sounds cool and I have some ideas on how to implement that. But, it's also advanced so I don't know if you need help on that or something else.

On a side note, are you using visual studio's form builder to create a resource file for the collection of controls? Or are you building the form out completely in code?

Here is some example code that hooks up controls to a window, the window is a small tool panel a part of a larger program.

Also, the code's forms are all prebuilt using the form builder so the program can reference any control with an application specific IDC_*

The most important things to make note is the use of the HWND variables and the WM_COMMAND proc in the main msgProc function. This is all related to how Windows communicates between forms / controls. A lot of information you need is stored in wParam and lParam and sometimes those can store multiple values.

This particular program I'm showing you used a lot of singleton delegates to achieve program data flow. But, now that I know more about how windows messages work I could do all of this with just message sending and catching.

Don't give up.

reference
http://msdn.microsoft.com/en-us/library/windows/desktop/bb773169%28v=vs.85%29.aspx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#pragma once
#include "d3dUtil.h"

class DialogWindow
{
protected:

	HWND m_dialogHWND;

public:
	DialogWindow() { m_dialogHWND = 0; }
	DialogWindow(HWND dialogHWND):m_dialogHWND(dialogHWND) {}
	virtual ~DialogWindow() { DestroyWindow(m_dialogHWND); }

	virtual BOOL CALLBACK DialogProc(HWND hwndDlg, UINT messge, WPARAM wParam, LPARAM lParam) = 0;

	HWND getHWND(){ return m_dialogHWND; }
	void setHWND(HWND hwnd) { m_dialogHWND = hwnd; }
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#pragma once
#include "DialogWindow.h"


class PropertyDialog : public DialogWindow
{
private:

	void Init(HWND hwnd);

	bool isChecked(HWND hwnd);

	//Graphics Subset
	void ToggleGraphics();
	void ToggleDiffuse();
	void ToggleBump();
	void ToggleNormal();
	void ToggleIllumination();
	void ToggleSpecular();

	void TurnDetailMapOFF(HWND combo, HWND check, bool &status);
	void TurnDetailMapON(HWND combo, HWND check, bool &status);

	void EnableDetailMap(HWND combo, bool &status);
	void DisableDetailMap(HWND combo, bool &status);

	void PopulateDetailMap(HWND combo, HWND check, std::string path, std::vector<std::string> &textureList, bool &status);

	void PerformTextureSwap(std::vector<std::string> TextureList, int index, int targetDetail);

	//void UpdateAI(MantisAI* AIObject);
	void UpdateGraphics(MantisMesh* graphicsObject);
	//void UpdatePhysics(MantisPhysics* physicsObject);
	//void UpdateGameplay(MantisGameplay* gameplayObject);

private:

	MantisMesh* m_SelectedGraphic;

	//Graphics Check box handels
	HWND m_GraphicsCheckHWND,
		 m_DiffuseCheckHWND,
		 m_BumpCheckHWND,
		 m_NormalCheckHWND,
		 m_IlluminationCheckHWND,
		 m_SpecularCheckHWND;

	//Graphics Combo box Handels
	HWND m_DiffuseComboHWND,
		 m_BumpComboHWND,
		 m_NormalComboHWND,
		 m_IlluminationComboHWND,
		 m_SpecularComboHWND,
		 m_ShaderComboHWND;

	HWND m_MaterialRED,
		 m_MaterialGREEN,
		 m_MaterialBLUE,
		 m_MaterialALPHA;
		 
	bool m_Graphics,
		 m_Diffuse,
		 m_Bump,
		 m_Normal,
		 m_Illumination,
		 m_Specular;

	std::vector<std::string> m_DiffuseTextures;
	std::vector<std::string> m_BumpTextures;
	std::vector<std::string> m_NormalTextures;
	std::vector<std::string> m_IlluminationTextures;
	std::vector<std::string> m_SpecularTextures;

public:
	PropertyDialog();
	~PropertyDialog();

	virtual BOOL CALLBACK DialogProc(HWND hwndDlg, UINT messge, WPARAM wParam, LPARAM lParam);

	void Update();
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//. . .
PropertyDialog::PropertyDialog()
{
	//Graphics Subset
	m_Graphics		= false;
	m_Diffuse		= false;
	m_Bump			= false;
	m_Normal		= false;
	m_Illumination	= false;
	m_Specular		= false;

	//***** Subset
}


PropertyDialog::~PropertyDialog()
{
	DestroyWindow(m_dialogHWND);
}

BOOL CALLBACK PropertyDialog::DialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
	switch(message)
	{
		case WM_INITDIALOG:
		{
			Init(hwndDlg);
			return TRUE;
		}

		case WM_COMMAND:
		{
			switch(LOWORD(wParam))
			{
				case IDC_CHECK1:
					ToggleGraphics();
					return TRUE;
				
				case IDC_CHECK_DIF:
					ToggleDiffuse();
					return TRUE;

				case IDC_CHECK_BMP:
					ToggleBump();
					return TRUE;
				
				case IDC_CHECK_NRM:
					ToggleNormal();
					return TRUE;
				
				case IDC_CHECK_ILL:
					ToggleIllumination();
					return TRUE;
				
				case IDC_CHECK_SPEC:
					ToggleSpecular();
					return TRUE;
				
				case IDCANCEL:
				{
					DestroyWindow(hwndDlg);
					WDM->ToggleProperty();
					delete this;
					return TRUE;
				}

				case IDC_COMBO_DIF:
				{
					switch(HIWORD(wParam))
					{
						case CBN_CLOSEUP:
						{
							PerformTextureSwap(m_DiffuseTextures, ComboBox_GetCurSel(m_DiffuseComboHWND), DIFFUSE_MAP);
							return TRUE;
						}
					}
					return TRUE;
				}
				
				case IDC_COMBO_BMP:
				{
					switch(HIWORD(wParam))
					{
						case CBN_CLOSEUP:
						{
							PerformTextureSwap(m_BumpTextures, ComboBox_GetCurSel(m_BumpComboHWND), BUMP_MAP);
							return TRUE;
						}
					}
					return TRUE;
				}
				
				case IDC_COMBO_NRM:
				{
					switch(HIWORD(wParam))
					{
						case CBN_CLOSEUP:
						{
							PerformTextureSwap(m_NormalTextures, ComboBox_GetCurSel(m_NormalComboHWND), NORMAL_MAP);
							return TRUE;
						}
					}
					return TRUE;
				}
				
				case IDC_COMBO_ILL:
				{
					switch(HIWORD(wParam))
					{
						case CBN_CLOSEUP:
						{
							PerformTextureSwap(m_IlluminationTextures, ComboBox_GetCurSel(m_IlluminationComboHWND), ILLUMINATION_MAP);
							return TRUE;
						}
					}
					return TRUE;
				}
								
				case IDC_COMBO_SPEC:
				{
					switch(HIWORD(wParam))
					{
						case CBN_CLOSEUP:
						{
							PerformTextureSwap(m_SpecularTextures, ComboBox_GetCurSel(m_SpecularComboHWND), SPECULAR_MAP);
							return TRUE;
						}
					}
					return TRUE;
				}
			}
			return TRUE;
		}
	}
	return FALSE;
} 

// Private Functions
//====================================

void PropertyDialog::Init(HWND hwnd)
{
	m_DiffuseComboHWND		= GetDlgItem(hwnd, IDC_COMBO_DIF);
	m_BumpComboHWND			= GetDlgItem(hwnd, IDC_COMBO_BMP);
	m_NormalComboHWND		= GetDlgItem(hwnd, IDC_COMBO_NRM);
	m_IlluminationComboHWND	= GetDlgItem(hwnd, IDC_COMBO_ILL);
	m_SpecularComboHWND		= GetDlgItem(hwnd, IDC_COMBO_SPEC);
	m_ShaderComboHWND		= GetDlgItem(hwnd, IDC_COMBO_SHADER);

	m_GraphicsCheckHWND		= GetDlgItem(hwnd, IDC_CHECK1);
	m_DiffuseCheckHWND		= GetDlgItem(hwnd, IDC_CHECK_DIF);
	m_BumpCheckHWND			= GetDlgItem(hwnd, IDC_CHECK_BMP);
	m_NormalCheckHWND		= GetDlgItem(hwnd, IDC_CHECK_NRM);
	m_IlluminationCheckHWND	= GetDlgItem(hwnd, IDC_CHECK_ILL);
	m_SpecularCheckHWND		= GetDlgItem(hwnd, IDC_CHECK_SPEC);

	m_MaterialRED			= GetDlgItem(hwnd, IDC_EDIT1);
	m_MaterialGREEN			= GetDlgItem(hwnd, IDC_EDIT11);
	m_MaterialBLUE			= GetDlgItem(hwnd, IDC_EDIT12);
	m_MaterialALPHA			= GetDlgItem(hwnd, IDC_EDIT2);
}
// . . . 


The piece of code that activates the above code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void WindowsDelegateMethods::ToggleProperty()
{
	if(!m_propertyOpen)
	{
		m_PropertyDialog = new PropertyDialog();
		m_DialogInitalizing = 14;

		HWND temp = CreateDialogParam(m_owningInstance,
									  MAKEINTRESOURCE(IDD_DIALOG5),
									  m_owningHandle,
									  m_owningDialogProc,
									  104);

		m_PropertyDialog->setHWND(temp);
		m_DialogInitalizing = 0;

		ShowWindow(temp, SW_SHOW);
	}

	m_propertyOpen = !m_propertyOpen;
}


Last edited on
you can complicate more than i ;)
please see my class:
- it's a label(the STATIC) class;
- when you create the window project, you must create the window procedure and message loop and the window itself;
- now imagine create a class with it's own window procedure;
- so you create the label(STATIC class) and the window procedure is automatic activated for these class.(the numbers of controls=the numbers of windows procedure.

but for that i must use the SetWindowLongPtr() for connect the control to window procedure.
i don't want be rude, but please continue with my own class or i can lose you :(
You don't use SetWindowLongPtr to connect the control to a windows procedure. From the given examples, you have to use an HWND to bridge the gap between the window procedure function and your static control.

See this article:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb775501%28v=vs.85%29.aspx

This article goes over how to create a static text control and how to get it drawn in a window using the WM_DRAWITEM proc as the means of referencing g_myStatic HWND to pull the information and to get it drawn. This can possibly help clear up why your label is not showing up.

But, in regards to this class you want I'm not sure I can help you because of a communication barrier.

If no one else will jump in all I can say is to look over the examples I posted. The first is how to implement a window inside of a class structure. The second is how to communicate with Controls. Take the class you want to implement and try to integrate it together until you get a solution that works for you.

If you get it to work I'm sure all of us here would love to see it so we can understand what you were trying to go for.

Have a good day :)
Last edited on
sorry the label is showed. the problem is Subclassing Controls(i think is the right term).
instead use the:

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
for all controls on that window, i want 1 for eatch control and another for the window.
the class create the control and it's own window procedure(Subclassing Controls).
(sorry my english... i'm trying)
after more search and work i activated the window procedure:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <windows.h>
#include <iostream>
#include <string>
#include <process.h>

using namespace std;
HWND hwnd;
HHOOK _hook;
WNDPROC previous_boring_subclassed_edit_proc;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_MOUSEMOVE:
            SetWindowText(hwnd,"hello");
        break;
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return CallWindowProc(previous_boring_subclassed_edit_proc, hwnd, msg, wParam, lParam);
    }
    return 0;
}

class label
{
private:





public:

    label(HWND value)
    {

        hwnd = CreateWindowEx(
            WS_EX_LEFT| WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
            "STATIC",
            "",
            SS_LEFT|WS_CHILD|WS_VISIBLE,
            0, 0, 100, 100,
            value,
            NULL,
            GetModuleHandle(NULL),
            NULL);

            ShowWindow(hwnd,SW_SHOW);
            UpdateWindow(hwnd);
            previous_boring_subclassed_edit_proc = (WNDPROC)GetWindowLong(hwnd, GWL_WNDPROC);//get the default procedure
            SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR)WndProc);//set your custom procedure :)
    }

    COORD GetSize()
    {
        RECT LabelSize;
        GetWindowRect(hwnd,&LabelSize);
        COORD crdSize={LabelSize.right-LabelSize.left,LabelSize.bottom-LabelSize.top};
        return crdSize;
    }

    void SetText(string text)
    {
        char* chrText=(char*)text.c_str();
        SetWindowText(hwnd, chrText);
    }


};

so what is the problem??
seems the msg const's aren't correct :(
but if i use a message box before the case it's showed. so what it's the problem?
You're fine, my friend. I appreciate your persistence in wanting to figure out the problem.

So I had a chance to really think about what you're trying to do and I feel it's similar to what I've been thinking about doing.

let's examine, together, what we want the end result to be. That way we can work backwards and figure out where the issue is and what needs to be made to get the desired result you want. It sounds like you want high level abstraction of the Windows controls so that coding it is very simple and yet the controls know how to automatically build out their procedure calls. Adding a button will make the window check the button and adding a label will have the window start drawing it.

Does this micro example look like something you'd want the end result to look like? Or am I still off? =\

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//Keep track of total program run time in seconds
double TimeElapsed;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
{
	//Create a blank window
	BlankWindow* myWindow = new BlankWindow(hInstance, 50, 50, 800, 600);

	//Closing this window will envoke
	//PostQuitMessage(0)
	myWindow->SetCanCloseApp(true); 

	//Create a Static Label with text "Hello World"
	StaticLabel* label1 = new StaticLabel(L"Hello World", 100, 100);	

	//Create a Static Label with text "I'm a simple control"
	StaticLabel* label2 = new StaticLabel(L"I'm a simple control", 300, 100);

	//Create a button with text "Clear Text"
	ButtonControl* myButton = new ButtonControl(L"Clear Text", 150, 300);

	//Add an event this button is associated with
	// EVENT_MOUSE_UP - Will trigger when button is let go of mouse
	// EVENT_LIMIT_NONE - Times this button can emit an event is not limited
	myButton->AddEvent(EVENT_MOUSE_UP, EVENT_LIMIT_NONE, [&](BaseControl* owningControl){

		ButtonControl* thisBtn = (ButtonControl*)owningControl;
		label1->SetText(L"<NULL>");
		label2->SetText(L"<NULL>");

		thisBtn->SetText(L"Jobs done");
		thisBtn->Disable();

		thisBtn->Super->Minimize();

	});

	//Add children controls to our window
	myWindow->AddChildControl(label1);
	myWindow->AddChildControl(label2);
	myWindow->AddChildControl(myButton);

	//====Start application main loop====//

	MSG msg;
	msg.message = WM_NULL;

	TimeElapsed = 0.0;

	__int64 countsPerSecond = 0;
	QueryPerformanceFrequency((LARGE_INTEGER*)&countsPerSecond);
	float secondsPerCount = 1.0f / (float)countsPerSecond;

	__int64 previousTimeStamp = 0;
	QueryPerformanceCounter((LARGE_INTEGER*)&previousTimeStamp);

	while (msg.message != WM_QUIT)
	{
		//Use to prevent update look freezing
		if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
		{
			//convert OS's raw message to
			//MSG struct
			TranslateMessage(&msg);

			//Send message to any window
			//that exsits in this appInstnace
			DispatchMessage(&msg);
		}
		else
		{
			__int64 currenTimeStamp = 0;
			QueryPerformanceCounter((LARGE_INTEGER*)&currenTimeStamp);
			double dt = (currenTimeStamp - previousTimeStamp) * secondsPerCount;
			previousTimeStamp = currenTimeStamp;

			//increment total time by this update's
			//time slice
			TimeElapsed += dt;

			//Update any time sensative code
			//and or systems
		}
	}

	return msg.wParam;
}
Oh, I also just realized what you're trying to do with GetWindowLongPtr in assigning your own proc. Sorry, I thought you saw what I did in one of my previous examples. Look above and notice the file BaseWindow.h and .cpp

I point those out because it's doing what you're trying to do but instead with a window.

I guess this means it's easier to do with a window since that is created with a custom WNDCLASSEX where you can explicitly assign the static callback function. The "STATIC" class is a bit less straight forward in changing.

I'll replicate what you have and see if I can debug it.
Last edited on
Ok, I fixed the class you posted to correctly have the subclassed WndProc hit. I commented out stuff that I changed.

Line 56 needed to be (LONG) instead of (LONG_PTR)

WndProc needed to be structured a bit different to make sure that 0 or a call to CallWindowProc is always hit on evaluation. When I was debugging the proc kept dying due to one of those stipulations not being met.

Only code I didn't include was a quick setup of a window and WinMain that initialized everything.

Only issue is that the Control is not getting correct messages sent to it. When I mouse over the text it shows up as the message 0x0132 when it should be WM_MOUSEMOVE so it doesn't work as intended =\

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <windows.h>
#include <iostream>
#include <string>
#include <process.h>

static HWND g_myStatic;

using namespace std;
HWND hwnd;
HHOOK _hook;
WNDPROC previous_boring_subclassed_edit_proc;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_MOUSEMOVE:
		SetWindowText(hwnd, L"hello");
		return 0;

	case WM_CLOSE:
		DestroyWindow(hwnd);
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}

	return CallWindowProc(previous_boring_subclassed_edit_proc, hwnd, msg, wParam, lParam);
}

class label
{
private:


	HWND m_hwnd;


public:

	label(HWND parentWindow)
	{

		m_hwnd = CreateWindowEx(
			0, 
			L"STATIC", 
			L"Some static text",
			WS_CHILD | WS_VISIBLE | SS_OWNERDRAW,
			25, 125, 150, 20, 
			parentWindow, 0, 0, 0);

		g_myStatic = m_hwnd;

		//hwnd = CreateWindowEx(
		//	WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
		//	L"STATIC",
		//	L"",
		//	SS_LEFT | WS_CHILD | WS_VISIBLE,
		//	0, 0, 100, 100,
		//	parentWindow,
		//	NULL,
		//	appInstance,
		//	NULL);

		ShowWindow(hwnd, SW_SHOW);
		UpdateWindow(hwnd);

		//previous_boring_subclassed_edit_proc = (WNDPROC)GetWindowLong(m_hwnd, GWL_WNDPROC);//get the default procedure
		//DWORD error = GetLastError();
		//SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR)WndProc);//set your custom procedure :)


		// Subclass the edit control. 
		previous_boring_subclassed_edit_proc = (WNDPROC)SetWindowLong(m_hwnd, GWL_WNDPROC, (LONG)WndProc);
	}

	COORD GetSize()
	{
		RECT LabelSize;
		GetWindowRect(hwnd, &LabelSize);
		COORD crdSize = { LabelSize.right - LabelSize.left, LabelSize.bottom - LabelSize.top };
		return crdSize;
	}

	void SetText(wstring text)
	{
		SetWindowText(hwnd, text.c_str());
	}

	HWND GetHWND() { return m_hwnd; }
};
sorry the 'L' gives me errors and the control isn't showed :(
(i'm using code blocks)
Pages: 12