PDA

Vollständige Version anzeigen : Benutzerdefiniertes Steuerelement


Thomas Thiele
01-11-2008, 05:47 PM
Hallo,

irgendwie stelle ich mich zu blöd an.
Ich habe auf einem modalen Dialog im Ressourcen-Editor (Visual C++
6.0) ein "Benutzerdefiniertes Steuerelement" und einen normalen Slider
angelegt.
Lösche ich das "Benutzerdefinierte Steuerelement" startet der Dialog
ganz normal mit Ok- und Cancel-Button und dem Slider. Lege ich es
wieder an, startet der Dialog nicht.

Der Dialog wird mit im der BUTTON_UP-Behandlungsroutine gestartet. Ist
nur Test.

hDlg = CreateDialog(hInst, MAKEINTRESOURCE (IDD_DIALOG1), hwnd,
(DLGPROC) DialogProc);
ShowWindow (hDlg, SW_SHOW);

hDlg ist 0 falls das "Benutzerdefinierte Steuerelement" vorhanden
ist.

Muss irgendwas ganz blödes sein ich sehe es aber nicht.
Kann mir jemand man einen Code posten in dem es geht? Einfach ein
einfacher Dialog, der ein besagtes "Benutzerdefinierte Steuerelement"
enthält und angezeigt wird.

Gruß Thomas

René König
01-11-2008, 06:17 PM
Hallo Thomas,

Thomas Thiele schrieb:
> hDlg ist 0 falls das "Benutzerdefinierte Steuerelement" vorhanden
> ist.

Du hast vermutlich vergessen, die Fensterklasse für das Steuerelement zu
registrieren. Das Registrieren (RegisterClass/Ex) muß bereits vor dem
Aufruf von CreateDialog erfolgt sein, in WM_INITDIALOG ist es zu spät.

Gruß,
René

Jörg Hauschild
01-11-2008, 06:17 PM
Thomas Thiele schrieb:
> Hallo,
>
> irgendwie stelle ich mich zu blöd an.
> Ich habe auf einem modalen Dialog im Ressourcen-Editor (Visual C++
> 6.0) ein "Benutzerdefiniertes Steuerelement" und einen normalen Slider
> angelegt.
> Lösche ich das "Benutzerdefinierte Steuerelement" startet der Dialog
> ganz normal mit Ok- und Cancel-Button und dem Slider. Lege ich es
> wieder an, startet der Dialog nicht.
>
> Der Dialog wird mit im der BUTTON_UP-Behandlungsroutine gestartet. Ist
> nur Test.
>
> hDlg = CreateDialog(hInst, MAKEINTRESOURCE (IDD_DIALOG1), hwnd,
> (DLGPROC) DialogProc);
> ShowWindow (hDlg, SW_SHOW);
>
> hDlg ist 0 falls das "Benutzerdefinierte Steuerelement" vorhanden
> ist.
>
> Muss irgendwas ganz blödes sein ich sehe es aber nicht.
> Kann mir jemand man einen Code posten in dem es geht? Einfach ein
> einfacher Dialog, der ein besagtes "Benutzerdefinierte Steuerelement"
> enthält und angezeigt wird.
>
> Gruß Thomas


Hallo Thomas,
Ein "Benutzerdefinierte Steuerelement" ist ja eine Fensterklasse, die Du
in Deinem Programm erstellen mußt, siehe "RegisterClass()".
Wahrscheinlich hast Du das nicht gemacht, oder in den Eintragungen im
Ressourceneditor die Klasse nicht angegeben.

Gruß Jörg

Thomas Thiele
01-11-2008, 06:52 PM
On 11 Jan., 19:17, René König <r...*tbkoenig.de> wrote:

> Du hast vermutlich vergessen, die Fensterklasse für das Steuerelement zu
> registrieren. Das Registrieren (RegisterClass/Ex) muß bereits vor dem
> Aufruf von CreateDialog erfolgt sein, in WM_INITDIALOG ist es zu spät.


Hallo,

in

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)

rufe ich folendes auf:

WNDCLASSEX sliderclassex = {0};
sliderclassex.cbSize = sizeof(WNDCLASSEX);
sliderclassex.style = CS_HREDRAW | CS_VREDRAW;
sliderclassex.lpfnWndProc = OwnProc;
sliderclassex.cbClsExtra = 0;
sliderclassex.cbWndExtra = 0;
sliderclassex.hInstance = hInst;
sliderclassex.hIcon = LoadIcon (NULL, IDI_APPLICATION);
sliderclassex.hCursor = LoadCursor (NULL, IDC_ARROW);
sliderclassex.hbrBackground = (HBRUSH) GetStockObject
(WHITE_BRUSH);
sliderclassex.lpszMenuName = NULL;
sliderclassex.lpszClassName = "OwnControl";
sliderclassex.hIconSm = sliderclassex.hIcon;

if (!RegisterClassEx (&sliderclassex))
{
MessageBox (NULL, TEXT ("RegisterClassEx für OwnControl
fehlgeschlagen!"),
"OwnControl", MB_ICONERROR);
return 0;
}

Geht trotzdem nicht.
CreateDialog wird erst beim Behandeln des BUTTON_UP Events
aufgerufen.

Ich poste mal den gesamten Code. Ist ja extra sehr rudimentär.

-------------------------- controldialog.cpp
----------------------------


#include <windows.h>
#include "resource.h"
#include <string>

// globale Variablen
HINSTANCE hInst;
HWND hDlg;

// Die Sliderprozedur
LRESULT CALLBACK OwnProc(HWND hwndDlg, UINT message, WPARAM wParam,
LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint (hwndDlg, &ps);
TextOut (hdc, 0, 0, "eigenes!", 27);
EndPaint (hwndDlg, &ps);
return (0);
}

return (FALSE);
}


// Prototypen
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT message, WPARAM wParam,
LPARAM lParam);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("Klassenname");
HWND hwnd;
MSG msg;
WNDCLASSEX wndclassex = {0};

wndclassex.cbSize = sizeof(WNDCLASSEX);
wndclassex.style = CS_HREDRAW | CS_VREDRAW;
wndclassex.lpfnWndProc = WndProc;
wndclassex.cbClsExtra = 0;
wndclassex.cbWndExtra = 0;
wndclassex.hInstance = hInstance;
wndclassex.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclassex.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclassex.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wndclassex.lpszMenuName = NULL;
wndclassex.lpszClassName = szAppName;
wndclassex.hIconSm = wndclassex.hIcon;

if (!RegisterClassEx (&wndclassex))
{
MessageBox (NULL, TEXT ("RegisterClassEx fehlgeschlagen!"),
szAppName, MB_ICONERROR);
return 0;
}

hInst = hInstance;

hwnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW, // erweiterter
Fensterstil
szAppName, // Name der Fensterklasse
TEXT ("Fenstertitel"), // Fenstertitel
WS_OVERLAPPEDWINDOW, // Fensterstil
CW_USEDEFAULT, // X-Position des
Fensters
CW_USEDEFAULT, // Y-Position des Fensters
CW_USEDEFAULT, // Fensterbreite
CW_USEDEFAULT, // Fensterhöhe
NULL, // übergeordnetes Fenster
NULL, // Menü
hInstance, // Programm-Kopiezähler (Programm-
ID)
NULL); // zusätzliche Parameter


//own klasse registrieren

WNDCLASSEX sliderclassex = {0};
sliderclassex.cbSize = sizeof(WNDCLASSEX);
sliderclassex.style = CS_HREDRAW | CS_VREDRAW;
sliderclassex.lpfnWndProc = SliderProc;
sliderclassex.cbClsExtra = 0;
sliderclassex.cbWndExtra = 0;
sliderclassex.hInstance = hInst;
sliderclassex.hIcon = LoadIcon (NULL, IDI_APPLICATION);
sliderclassex.hCursor = LoadCursor (NULL, IDC_ARROW);
sliderclassex.hbrBackground = (HBRUSH) GetStockObject
(WHITE_BRUSH);
sliderclassex.lpszMenuName = NULL;
sliderclassex.lpszClassName = "OwnControl";
sliderclassex.hIconSm = sliderclassex.hIcon;

if (!RegisterClassEx (&sliderclassex))
{
MessageBox (NULL, TEXT ("RegisterClassEx für OwnControl
fehlgeschlagen!"),
"OwnControl", MB_ICONERROR);
return 0;
}

ShowWindow (hwnd, iCmdShow);
UpdateWindow (hwnd);


while (GetMessage (&msg, NULL, 0, 0))
{
// Damit der Dialog die Nachrichten über Tastaturereignisse
bekommt
// müssen wir hier "IsDialogMessage()" einbauen!
if (!IsWindow(hDlg) || !IsDialogMessage(hDlg, &msg))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
return msg.wParam;
}

// Die Hauptnachrichtenschleife
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;

switch (message)
{
case WM_CREATE:
hDlg = NULL;
return (0);

case WM_RBUTTONUP:

if (hDlg == NULL) // Den Dialog nur erzeugen, wenn noch keiner
da ist.
{
hDlg = CreateDialog(hInst, MAKEINTRESOURCE (IDD_DIALOG1),
hwnd, (DLGPROC) DialogProc);
if (hDlg != 0){
MessageBox (NULL, TEXT ("hDlg ungleich 0"), TEXT
("WM_RBUTTONUP"), MB_ICONERROR);
}
else {
MessageBox (NULL, TEXT ("hDlg gleich 0"), TEXT
("WM_RBUTTONUP"), MB_ICONERROR);
}
int ret = ShowWindow (hDlg, SW_SHOW);
}

return (0);

case WM_PAINT:
hdc = BeginPaint (hwnd, &ps);
TextOut (hdc, 0, 0, "Hauptfenster - bitte rechte Mausetaste
drücken!", 27);
EndPaint (hwnd, &ps);
return (0);

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

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



// Die Dialogprozedur
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT message, WPARAM wParam,
LPARAM lParam)
{
HWND hwnd;

static HBRUSH hBrush; //muss static sein, sonst klappt das Löschen
nicht

switch (message)
{
case WM_INITDIALOG:

/* hwnd = CreateWindowEx ("OwnControl"
"OwnControl", // Name der Fensterklasse
TEXT ("Fenstertitel"), // Fenstertitel
WS_OVERLAPPEDWINDOW, // Fensterstil
CW_USEDEFAULT, // X-Position des
Fensters
CW_USEDEFAULT, // Y-Position des Fensters
CW_USEDEFAULT, // Fensterbreite
CW_USEDEFAULT, // Fensterhöhe
hwndDlg, // übergeordnetes Fenster
NULL, // Menü
hInst, // Programm-Kopiezähler (Programm-ID)
NULL); // zusätzliche Parameter
*/
hwnd = CreateWindow("OwnControl", "OwnControl", WS_CHILD |
WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hwndDlg, NULL, GetModuleHandle(NULL), NULL);
if (hwnd == 0)
{
MessageBox(NULL, "PluginSlider creation failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}



hBrush = (HBRUSH) CreateSolidBrush (RGB ( 255, 100, 100)); //
Brush erzeugen (gelb)
return (TRUE);

case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
DestroyWindow (hwndDlg);
return (TRUE);

default:
break;
}
return (FALSE);

//farbe von textfeld ändern
case WM_CTLCOLOREDIT:
//Damit der Schrifthintergrund nicht stört, machen wir das
Editfeld transparent
SetBkMode ((HDC) wParam, TRANSPARENT);
return (LONG) hBrush; // Hintergrund färben


case WM_CLOSE:
case WM_DESTROY:
hDlg = NULL;
EndDialog (hwndDlg, 0);
return (TRUE);
}

return (FALSE);


}



//----------------------------- resource.rc
--------------------------------

//Microsoft Developer Studio generated resource script.
//
#include "resource.h"

// Generated Help ID header file
#define APSTUDIO_HIDDEN_SYMBOLS
#include "resource.hm"
#undef APSTUDIO_HIDDEN_SYMBOLS

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// Deutsch (Deutschland) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
#ifdef _WIN32
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
#pragma code_page(1252)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END

3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END

#endif // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_DIALOG1 DIALOGEX 0, 0, 242, 141
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,185,7,50,14
PUSHBUTTON "Abbrechen",IDCANCEL,185,24,50,14
EDITTEXT IDC_TEXTFIELD,166,65,50,18,ES_AUTOHSCROLL | NOT
WS_BORDER,0,HIDC_TEXTFIELD
CONTROL "Custom1",IDC_CSLIDER,"OwnControl",WS_TABSTOP |
0x18,22,
60,128,25
CONTROL "Slider1",IDC_SLIDER1,"msctls_trackbar32",TBS_BOTH
|
TBS_NOTICKS | WS_TABSTOP,21,14,100,15
END


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 235
TOPMARGIN, 7
BOTTOMMARGIN, 134
END
END
#endif // APSTUDIO_INVOKED

#endif // Deutsch (Deutschland) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED




----------------------- resource.h -----------------------

//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by resource.rc
//
#define IDD_DIALOG1 101
#define IDC_TEXTFIELD 1000
#define IDC_CSLIDER 1002
#define IDC_SLIDER1 1003

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1004
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

Thomas Thiele
01-11-2008, 06:56 PM
On 11 Jan., 19:17, Jörg Hauschild <joerg-hausch...*t-online.de> wrote:

> Hallo Thomas,
> Ein "Benutzerdefinierte Steuerelement" ist ja eine Fensterklasse, die Du
> in Deinem Programm erstellen mußt, siehe "RegisterClass()".
> Wahrscheinlich hast Du das nicht gemacht, oder in den Eintragungen im
> Ressourceneditor die Klasse nicht angegeben.

Sagen wir mal so: ich habe daran gedacht und es auch versucht.
Siehe geposteten Code in der Antwort an Rene.

René König
01-11-2008, 07:28 PM
Hallo Thomas,

in diesem Fall ist Dein eigenes Control gar nicht Schuld am Fehlschlag.
Es liegt vielmehr daran:

> CONTROL "Slider1",IDC_SLIDER1,"msctls_trackbar32",TBS_BOTH

Hierbei handelt es sich um ein sogenanntes CommonControl. Die
Fensterklasse dafür wird nicht per Default registriert, das musst Du
schon selbst erledigen. Dafür gibt es die beiden Funktionen
InitCommonControls und InitCommonControlsEx, such Dir eine aus:

http://msdn2.microsoft.com/en-us/library/bb775695.aspx
http://msdn2.microsoft.com/en-us/library/bb775697(VS.85).aspx

Ach ja, da ist noch was:

> // Die Sliderprozedur
> LRESULT CALLBACK OwnProc(HWND hwndDlg, UINT message, WPARAM wParam,
> LPARAM lParam)
> {
> HDC hdc;
> PAINTSTRUCT ps;
> switch (message)
> {
> case WM_PAINT:
> hdc = BeginPaint (hwndDlg, &ps);
> TextOut (hdc, 0, 0, "eigenes!", 27);
> EndPaint (hwndDlg, &ps);
> return (0);
> }
>
> return (FALSE);
> }

Wenn ich das richtig verstehe, handelt es sich hier um eine ganz normale
Fenster-Prozedur, nicht um eine DialogProc (schon allein wegen LRESULT).
Eine solche Fenster-Prozedur verlässt Du nicht mit FALSE im
Default-Falle, sondern per Aufruf von DefWindowProc.

Gruß,
René

Thomas Thiele
01-11-2008, 11:59 PM
René König schrieb:
> Hallo Thomas,
>
> in diesem Fall ist Dein eigenes Control gar nicht Schuld am Fehlschlag.
> Es liegt vielmehr daran:
>
> > CONTROL "Slider1",IDC_SLIDER1,"msctls_trackbar32",TBS_BOTH
>
> Hierbei handelt es sich um ein sogenanntes CommonControl. Die
> Fensterklasse dafür wird nicht per Default registriert, das musst Du
> schon selbst erledigen. Dafür gibt es die beiden Funktionen
> InitCommonControls und InitCommonControlsEx, such Dir eine aus:

Verstehe ich nicht. Wieso klappst dann wenn der eigene Controller, das
"benutzerdefinierte Steuerelement" fehlt.
Also z.B. die Zeile in der *.rc gelöscht/auskommentiert wird?

> Wenn ich das richtig verstehe, handelt es sich hier um eine ganz normale
> Fenster-Prozedur, nicht um eine DialogProc (schon allein wegen LRESULT).
> Eine solche Fenster-Prozedur verlässt Du nicht mit FALSE im
> Default-Falle, sondern per Aufruf von DefWindowProc.

Huch, so hatte ich das aber im Beispiel auch so gesehen.
Muss ich nochmal schauen.

Ich probier das demnächst mal aus. Jetzt nicht mehr...;-)

Thomas Thiele
01-14-2008, 07:07 PM
Hallo,

ich muss noch mal "nerven".

Ich bekomme es einfach nicht. Common Controls initialisiert.
Das Dialoghandle was CreateDialog zurückliefert ist immer 0.
LastError ist 87 "invalid parameter".
Allein welcher wo und wie, keine Ahnung.

Die Dialog-Behandlungsroutine wird zwar aufgerufen, aber nicht mit
WM_CREATE oder WM_INITDIALOG, sondern nur mit WM_SETFONT und dann gleich
WM_NCDESTROY.

Kann mit jemand mal ein Beispiel geben, wo im Ressouren-Editor einfach
ein 0815-Dialog angelegt wird mit OK- und Cance-Button und einem
"benutzerdefinierten Steuerelement"?
Sobald das enthalten ist, geht der Dialog nicht mehr auf. Mit den
beschriebenen Symptomen. Wird das Teil wieder gelöscht funktioniert
alles wunderbar.

Notfalls kann ich den letzten compilefähigen Code mal posten.