Moin moin,

I'm new to this forum and this is my first post, so I want to use this opportunity to say moin moin

OK, but now back to topic.

I would like to create a custom control class, at first a simple button.
During my investigations about this affair I found a lot of articles and forum requests.
There are several methods to realize it, but mostly there's a snag on it.

Then I found some solutions working with derived classes to get rid of some disadvantages of other methods.
"Scintilla" is a good examle for that what I want to do, but I don't understand all of the code and don't know what also depends to get it work like this.

I thought by myself: "OK, no problem ...", but in fact after weeks of investigation and playing around with it, I'm fully frustrated ...

I can't get it run in any way !!!

So, please, could someone take notice of my problem and help me to solve it ?

Here's a little example of my failing code:
BaseCtrl.h
Code:
#ifndef _BASECTRL_H_
#define _BASECTRL_H_

#include <windows.h>


class BaseCtrl {
  public:
	BaseCtrl() {}
	BaseCtrl(HWND hWindow)
	: hWndCtrl(hWindow) {
	}
	virtual ~BaseCtrl() {}

	static bool RegisterCtrlClass(LPCTSTR szClassName);

  protected:
	// Statische Fensterprozedur
	static LRESULT CALLBACK stWndProc(HWND, UINT, WPARAM, LPARAM);
	// Virtuelle Fensterprozedur zur Verarbeitung der Nachrichten
	virtual LRESULT MessageProc(HWND, UINT, WPARAM, LPARAM);

	HWND  hWndCtrl;
	HMENU ctrlID;

};

bool BaseCtrl::RegisterCtrlClass(LPCTSTR szClassName) {

	WNDCLASSEX wcl;

    wcl.hInstance      = reinterpret_cast<HINSTANCE>(::GetModuleHandle(0));
    wcl.lpszClassName  = szClassName;
	wcl.lpfnWndProc    = ::BaseCtrl::stWndProc;
    wcl.style          = CS_DBLCLKS;
    wcl.cbSize         = sizeof(WNDCLASSEX);
    wcl.hIcon          = NULL;
    wcl.hIconSm        = NULL;
    wcl.hCursor        = NULL;
    wcl.lpszMenuName   = NULL;
    wcl.cbClsExtra     = 0;
    wcl.cbWndExtra     = sizeof(BaseCtrl *);
    wcl.hbrBackground  = reinterpret_cast<HBRUSH>(::GetStockObject(BLACK_BRUSH));

    if (!::RegisterClassEx (&wcl)) {
        return false;
    } else {
        return true;
    }
}

LRESULT CALLBACK BaseCtrl::stWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

	BaseCtrl *pCtrl = reinterpret_cast<BaseCtrl *>(::GetWindowLong(hwnd, 0));

	if (!pCtrl) {
		if (msg == WM_NCCREATE) {
			pCtrl = new BaseCtrl(hwnd);
			::SetWindowLong(hwnd, 0, reinterpret_cast<LONG>(pCtrl));
			return pCtrl->MessageProc(hwnd, msg, wParam, lParam);
		} else {
			return ::DefWindowProc(hwnd, msg, wParam, lParam);
		}
	} else {
		if (msg == WM_NCDESTROY) {
			delete pCtrl;
			return ::DefWindowProc(hwnd, msg, wParam, lParam);
		} else {
			return pCtrl->MessageProc(hwnd, msg, wParam, lParam);
		}
	}
}

LRESULT BaseCtrl::MessageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

	return 0;
}
#endif
ButtonCtrl.h
Code:
#ifndef _BUTTONCTRL_H_
#define _BUTTONCTRL_H_

#include "BaseCtrl.h"

const wchar_t szBtnClassName [] = TEXT("BUTTONCLASS");

void RegisterButtonClass() {
	if (!BaseCtrl::RegisterCtrlClass(szBtnClassName)) {
		::MessageBox(NULL, TEXT("NOT REGISTERED"), TEXT("NO"), MB_ICONINFORMATION);
}

class ButtonCtrl : public BaseCtrl {
  public:
	ButtonCtrl() {}
	ButtonCtrl(HWND hWindow)
		: BaseCtrl(hWindow) {
	}
	virtual ~ButtonCtrl() {}

  private:
	virtual LRESULT MessageProc(HWND, UINT, WPARAM, LPARAM);

};

LRESULT ButtonCtrl::MessageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {

	switch (msg) {
		case WM_CREATE:
			::MessageBox(NULL, TEXT("ButtonCtrl::MessageProc"), TEXT("WM_CREATE"), MB_ICONINFORMATION);
			break;
		default:
			return ::DefWindowProc(hwnd, msg, wParam, lParam);
	}
	return 0;
}
#endif
main.cpp for testing ...
Code:
#include "ButtonCtrl.h"

#define IDC_BUTTON_1    1

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

const wchar_t szClassName[] = TEXT("MainWndClass");

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
    HWND       hwnd;
    MSG        messages;
    WNDCLASSEX wincl;

    wincl.hInstance      = hInstance;
    wincl.lpszClassName  = szClassName;
    wincl.lpfnWndProc    = WindowProcedure;
    wincl.style          = CS_DBLCLKS;
    wincl.cbSize         = sizeof (WNDCLASSEX);
    wincl.hIcon          = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm        = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor        = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName   = NULL;
    wincl.cbClsExtra     = 0;
    wincl.cbWndExtra     = 0;
    wincl.hbrBackground  = (HBRUSH) COLOR_BACKGROUND;

    if (!RegisterClassEx (&wincl))
        return 0;

    hwnd = CreateWindowEx (
           0,
           szClassName,
           TEXT("Test the Custom Control ..."),
           WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
           CW_USEDEFAULT,
           CW_USEDEFAULT,
           544,
           375,
           HWND_DESKTOP,
           NULL,
           hInstance,
           NULL
           );


    ShowWindow  (hwnd, nCmdShow);
    UpdateWindow(hwnd);


    while (GetMessage (&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage (&messages);
    }

    return messages.wParam;
}



LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HWND hwndButton;
    HWND hwndBut;
    static HINSTANCE hInst = (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE);

    switch (message)
    {
        case WM_CREATE:
			RegisterButtonClass();

            // Test the new class :) -> ;(
            hwndButton = CreateWindowEx(0, TEXT("BUTTONCLASS"), TEXT(""),
                                WS_CHILD | WS_VISIBLE | WS_POPUP | WS_TABSTOP | WS_CLIPSIBLINGS,
                                20, 20, 100, 25,
                                hwnd, (HMENU) IDC_BUTTON_1, hInst, NULL);


            hwndBut    = CreateWindowEx(0, TEXT("Button"), TEXT(""),
                                WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_CLIPSIBLINGS,
                                60, 60, 100, 25,
                                hwnd, (HMENU) 2, hInst, NULL);
            break;

        case WM_DESTROY:
            PostQuitMessage (0);
            break;

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

    return 0;
}
Sorry, the code isn't well commented ...

The problem is that the static stWndProc isn't called !!!
So what's wrong in my code ???

Scintilla is mostly doin' the same like I do, isn't it ?

Many thanx for taking notice.


Greetz
Greenhorn

p.s.: Sorry for my bad english, I hope you understand what I want to express ...