D
hier mein code (hat etwas gedauert)
Zuallererst mal die Keklaration der Klasse:
/* ************************************************************************** *
* MyButton.h *
* MyButton - Buttonklasse Deklaration *
* (c) 2002 by DocJunioR *
* erstellt: 31.10.2002 v 0.1 *
* ************************************************************************** *
* Änderungen : Datum * Änderung *
* * *
* ************************************************************************** */
#include <windows.h>
#include <commctrl.h>
#include <winuser.h>
/* ***** MyButtonMessages ************************************************* */
#define MBM_NORMAL 0
#define MBM_CLICKED 1
#define MBM_DEACTIVATED 2
#define MBM_HOVER 4
class C_MyButton
{
/* ***** Variablen ******************************************************** */
private:
int Status;
int PosX, PosY;
WNDCLASS wincl;
MSG msg;
HWND parentwnd;
BITMAP B_Normal, B_Active, B_Deacti, B_Hover;
HBITMAP H_Normal, H_Active, H_Deacti, H_Hover;
HDC hdc, hdcMem;
UINT smsg;
/* ***** Funtionen ******************************************************** */
public:
HWND hwnd;
static LRESULT CALLBACK ChildProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam);
C_MyButton (HWND hWndP, HINSTANCE hInstance,
int x, int y,
LPSTR Norm, LPSTR Dis, LPSTR Toggl,
LPSTR Hov, UINT BMsg);
~C_MyButton();
};
dann kommen die Methoden.
Achtung: ich hab HD hier außerhalb der Klasse, was Arg unsauber ist!!
Hab damit nur was getestet. man sollte es als Static in die ChildProc aufnehmen!
/* ************************************************************************** *
* MyButton.cpp *
* MyButton - Buttonklasse Methoden *
* (c) 2002 by DocJunioR *
* erstellt: 31.10.2002 v 0.1 *
* ************************************************************************** *
* Änderungen : Datum * Änderung *
* * *
* ************************************************************************** */
#include "c_mybutton.h"
int HD = 0;
C_MyButton::C_MyButton (HWND hWndP, HINSTANCE hInstance,
int x, int y,
LPSTR Norm, LPSTR Dis, LPSTR Toggl,
LPSTR Hov, UINT BMsg)
{
PosX = x, PosY = y;
Status = MBM_NORMAL;
smsg = BMsg;
parentwnd = hWndP;
/* ***** Fensterklasse initialisieren ************************************* */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.hIcon = NULL;
wincl.hInstance = hInstance;
wincl.lpfnWndProc = ChildProc; /* This function is called by windows */
wincl.lpszClassName = "MyButton";
wincl.lpszMenuName = NULL; /* No menu */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
RegisterClass(&wincl);
/* ***** Bilder laden ***************************************************** */
H_Normal = (HBITMAP) LoadImage(hInstance, Norm, IMAGE_BITMAP, 0 , 0,
LR_DEFAULTSIZE | LR_LOADFROMFILE | LR_CREATEDIBSECTION);
H_Active = (HBITMAP) LoadImage(hInstance, Toggl, IMAGE_BITMAP, 0 , 0,
LR_DEFAULTSIZE | LR_LOADFROMFILE | LR_CREATEDIBSECTION);
H_Deacti = (HBITMAP) LoadImage(hInstance, Dis, IMAGE_BITMAP, 0 , 0,
LR_DEFAULTSIZE | LR_LOADFROMFILE | LR_CREATEDIBSECTION);
H_Hover = (HBITMAP) LoadImage(hInstance, Hov, IMAGE_BITMAP, 0 , 0,
LR_DEFAULTSIZE | LR_LOADFROMFILE | LR_CREATEDIBSECTION);
GetObject (H_Normal, sizeof(BITMAP), &B_Normal);
GetObject (H_Active, sizeof(BITMAP), &B_Active);
GetObject (H_Deacti, sizeof(BITMAP), &B_Deacti);
GetObject (H_Hover, sizeof(BITMAP), &B_Hover);
hwnd = CreateWindow("MyButton", "\0", WS_CHILD|WS_VISIBLE, PosX, PosY,
B_Normal.bmWidth, B_Normal.bmHeight,
hWndP, NULL, (HINSTANCE) GetWindowLong (hWndP, GWL_HINSTANCE),
NULL);
SetWindowLong(hwnd, GWL_USERDATA, (long) this);
}
C_MyButton::~C_MyButton()
{
DeleteObject(H_Normal);
DeleteObject(H_Active);
DeleteObject(H_Deacti);
DeleteObject(H_Hover);
}
LRESULT CALLBACK C_MyButton::ChildProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
// Weil reine Zuweisung in static nicht geht
C_MyButton *Bt = (C_MyButton*) GetWindowLong(hWnd, GWL_USERDATA);
PAINTSTRUCT ps;
TRACKMOUSEEVENT tme; // Mausbewegung verfolgen
switch (message)
{
case WM_LBUTTONDOWN:
if (!(Bt->Status & MBM_CLICKED)) Bt->Status = MBM_CLICKED;
InvalidateRect(Bt->hwnd, NULL, FALSE);
return 0;
case WM_LBUTTONUP:
// Message an Fenster senden um zu reagieren
SendMessage(Bt->parentwnd, Bt->smsg, Bt->Status & MBM_DEACTIVATED, lParam);
Bt->Status = MBM_NORMAL;
HD = 0;
InvalidateRect(Bt->hwnd, NULL, FALSE);
return 0;
case WM_MOUSEMOVE:
if (HD == 0)
{
HD = 1;
Bt->Status += MBM_HOVER; // OnMouseOver
}
// Melden, wenn Button verlassen wurde
tme.hwndTrack=Bt->hwnd;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
TrackMouseEvent(&tme);
InvalidateRect(Bt->hwnd, NULL, FALSE);
return 0;
case WM_MOUSELEAVE:
Bt->Status -= MBM_HOVER; // OnMouseOut
HD = 0;
InvalidateRect(Bt->hwnd, NULL, FALSE);
return 0;
case WM_SIZE:
return 0;
case WM_PAINT:
Bt->hdc = BeginPaint(hWnd, &ps);
Bt->hdcMem = CreateCompatibleDC(Bt->hdc);
if (Bt->Status == MBM_DEACTIVATED)
SelectObject (Bt->hdcMem, Bt->H_Deacti);
else if (Bt->Status == MBM_HOVER)
SelectObject (Bt->hdcMem, Bt->H_Hover);
else if (Bt->Status == (MBM_CLICKED) || Bt->Status == (MBM_CLICKED + MBM_HOVER))
SelectObject (Bt->hdcMem, Bt->H_Active);
else
SelectObject (Bt->hdcMem, Bt->H_Normal);
BitBlt( Bt->hdc, 0, 0, Bt->B_Normal.bmWidth,
Bt->B_Normal.bmHeight, Bt->hdcMem, 0, 0, SRCCOPY);
DeleteDC (Bt->hdcMem);
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}
und zuguter Letzt nun noch die Testfunktion.
/* ************************************************************************** *
* TestButton.cpp *
* MyButton - Buttonklasse Testfenster *
* (c) 2002 by DocJunioR *
* erstellt: 31.10.2002 v 0.1 *
* ************************************************************************** *
* Änderungen : Datum * Änderung *
* * *
* ************************************************************************** */
#include <windows.h>
#include "c_mybutton.h"
#define WM_BUTTON1 (WM_USER + 1)
#define WM_BUTTON2 (WM_USER + 2)
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Make the class name into a global variable */
char szClassName[ ] = "WindowsApp";
int WINAPI
WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
C_MyButton *B1, *B2;
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default color as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"Windows App", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
544, /* The programs width */
375, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
/* Make the window visible on the screen */
ShowWindow (hwnd, nFunsterStil);
B1 = new C_MyButton(hwnd, hThisInstance, 30, 30,
"gfx/TN.bmp","gfx/TDis.bmp","gfx/TTog.bmp","gfx/THov.bmp",
WM_BUTTON1);
B2 = new C_MyButton(hwnd, hThisInstance, 30, 90,
"gfx/TN.bmp","gfx/TDis.bmp","gfx/TTog.bmp","gfx/THov.bmp",
WM_BUTTON2);
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK
WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
case (WM_BUTTON1):
// MessageBox(NULL,"No 1", "erster", MB_OK);
break;
case (WM_BUTTON2):
// MessageBox(NULL,"No 2", "zweiter", MB_OK);
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
Die Buttons sind bmps beliebiger Größe. Allerdings müssen sie schon alle die gleiche Größe haben. Ansonsten wird sich an der größe des normalen Button orientiert.
das Deaktivieren von Buttons ist noch nicht drin, ist aber eigentlich kein Problem. Wie gesagt, ich hab erst vorgestern damit begonnen..
cYa
DjR