#include <windows.h>
#include <commctrl.h>
#include "resource.h"
// ############## ID TOOLBAR-a ####################
#define TB_ID 100
// ############## ID PRZYCISKÓW TOOLBARD-a ##############
#define ID_LINE 100
#define ID_CIRCLE 101
#define ID_RECTANGLE 102
#define ID_SELECT 103
// ###################### UCHWYT TOOLBAR-a ##########################
HWND toolbar;
// ###################### UCHWYT STATUSBAR-a ########################
HWND statusbar;
// ###################### ID STATUSBAR-a ############################
#define SB_ID 101
// ###################### ID OKNA RYSOWANIA #########################
#define ID_DRAWING 102
// ####################### UCHWYT OKNA RYSOWANIA ####################
HWND drawingWnd;
// ################## PROCEDURA OKNA GŁÓWNEGO #######################
LRESULT CALLBACK WndParentProc(HWND hParent, UINT msg, WPARAM wParam, LPARAM lParam){
static RECT parent_rect;
switch(msg){
case WM_SIZE:
{
SetRect(&parent_rect, 0, 0, LOWORD(lParam), HIWORD(lParam)); // pobieram rozmiar okna
SendMessage(toolbar, TB_AUTOSIZE, NULL, NULL); // okunikat wysyłany w celu automatycznego ustawienia wymiarów okna toolbar
SetWindowPos(statusbar, 0, 0, 0, 0, 0, SWP_NOZORDER); // automatyczne dostosowanie szerokości okna kontrolki statusbar-u do okna rodzica
RECT sb_r;
RECT tb_r;
GetClientRect(toolbar, &tb_r); // pobieram wymiary okna kontrolki toolbar
GetClientRect(statusbar, &sb_r); // pobieram wymiary okna kontrolki statusbar
SetWindowPos(drawingWnd, NULL, 0, tb_r.bottom, parent_rect.right, parent_rect.bottom - sb_r.bottom - tb_r.bottom,SWP_NOZORDER); // ustawiam wymiary okna potomnego związango z obsługa rysowania
}
break;
case WM_COMMAND:
{
SendMessage(drawingWnd, msg, wParam, lParam); // przekazuję obsługę komunikatów WM_COMMAND do okna rysowania
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
}
return DefWindowProc(hParent,msg, wParam, lParam);
}
// ################################### Procedura okna dokumentu #####################################
LRESULT CALLBACK WndDrawingProc(HWND hWndDraw, UINT msg, WPARAM wParam, LPARAM lParam){
static POINT mousepos; // współrzędne kursora w oknie
switch(msg){
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWndDraw, &ps);
EndPaint(hWndDraw, &ps);
}
break;
case WM_MOUSEMOVE:
{
mousepos.x = LOWORD(lParam); // pobieranie współrzędnej x
mousepos.y = HIWORD(lParam); // pobieranie współrzędnej y
wchar_t buffor[100]; // bufor do konwersji na tekst
wsprintf(buffor, L"X = %i",mousepos.x); // konwersja na tekst współrzędnej x
SendMessage(statusbar, SB_SETTEXT, 0, (LPARAM)buffor); // ustawienie tekstu pierwszej pozycji paska kontrolki statusbar
wsprintf(buffor, L"Y = %i",mousepos.y); // konwersja na tekst współrzędnej y
SendMessage(statusbar, SB_SETTEXT, 1, (LPARAM)buffor); // ustawienie tekstu drugiej pozycji paska kontrolki statusbar
}
break;
case WM_COMMAND:
{
if((HWND)lParam == toolbar){
switch(LOWORD(wParam)){
case ID_LINE: // komunikat przychodzący od przycisku toolbar-a o identyfikatorze ID_LINE
{
SendMessage(statusbar, SB_SETTEXT, 2, (LPARAM)L"Rysowanie linii"); // ustawienie tekstu w ostatnim polu statusbar-u
}
break;
case ID_CIRCLE: // to samo co poprzednio, tylko dla ID_CIRCLE
{
SendMessage(statusbar, SB_SETTEXT, 2, (LPARAM)L"Rysowanie okręgu"); // ustawienie tekstu w ostatnim polu statusbar-u
}
break;
case ID_RECTANGLE: // to samo co poprzednio, tylko dla ID_RECTANGLE
{
SendMessage(statusbar, SB_SETTEXT, 2, (LPARAM)L"Rysowanie prostokąta"); // ustawienie tekstu w ostatnim polu statusbar-u
}
break;
case ID_SELECT: // to samo co poprzednio, tylko dla ID_SELECT
{
SendMessage(statusbar, SB_SETTEXT, 2, (LPARAM)L"Rysowanie edycja"); // ustawienie tekstu w ostatnim polu statusbar-u
}
break;
}
}
}
break;
}
return DefWindowProc(hWndDraw, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int){
// ####################### Operacje związane z rejestracją okna głównego ########################
wchar_t parentWndClass[] = L"Okno główne programu Rysowanie";
wchar_t drawingWndClass[] = L"Okno rysowania";
WNDCLASS wnd;
wnd.cbClsExtra = NULL;
wnd.cbWndExtra = NULL;
wnd.hbrBackground = NULL;
wnd.hCursor = LoadCursor(NULL, IDC_ARROW);
wnd.hIcon = LoadIcon(NULL, IDC_ICON);
wnd.hInstance = hInst;
wnd.lpfnWndProc = WndParentProc;
wnd.lpszClassName = parentWndClass;
wnd.lpszMenuName = NULL;
wnd.style = CS_VREDRAW|CS_HREDRAW;
if(!RegisterClass(&wnd)){
MessageBox(NULL, L"Nie zarejestrowano klasy okna", L"Błąd", MB_OK);
return 0;
}
wnd.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wnd.hCursor = LoadCursor(NULL, IDC_CROSS);
wnd.hIcon = LoadIcon(NULL, IDC_ICON);
wnd.hInstance = hInst;
wnd.lpfnWndProc = WndDrawingProc;
wnd.lpszClassName = drawingWndClass;
wnd.lpszMenuName = NULL;
if(!RegisterClass(&wnd)){
MessageBox(NULL, L"Nie zarejestrowano klasy okna rysowania", L"Błąd", MB_OK);
return 0;
}
HWND parent_window = CreateWindow(parentWndClass, L"Rysowanie", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL);
// #################### Tworzenie własnego okna potomnego ############################
drawingWnd = CreateWindow(drawingWndClass, L"Rysowanie", WS_CHILD|WS_VISIBLE, 0, 0, 100, 100, parent_window, (HMENU)ID_DRAWING, hInst, NULL);
// ################# Inicjalizowanie tablicy struktur niezbędnej do utworzenia toolbar-a #########################
TBBUTTON bt[4]; // tablica struktur przycisków toolbar-a
int i = 0; // indeks
bt[i].dwData = 0; // brak dodatkowych danych
bt[i].fsState = TBSTATE_ENABLED; // stan przycisku (w tym przypadku odblokowany)
bt[i].fsStyle = TBSTYLE_CHECKGROUP; // styl przycisku (w tym przypadku grupowanie z innymi przyciskami)
bt[i].iBitmap = i; // indeks wycinka bitmay
bt[i].idCommand = ID_LINE; // identyfikator przycisku dla rysowania linii
bt[i].iString = i; // indeks tekstu wyświetlanego pod przyciskiem
i++;
bt[i].dwData = 0;
bt[i].fsState = TBSTATE_ENABLED;
bt[i].fsStyle = TBSTYLE_CHECKGROUP;
bt[i].iBitmap = i;
bt[i].idCommand = ID_CIRCLE; // idnetyfikator przycisku dla rysowania okręgu
bt[i].iString = i;
i++;
bt[i].dwData = 0;
bt[i].fsState = TBSTATE_ENABLED;
bt[i].fsStyle = TBSTYLE_CHECKGROUP;
bt[i].iBitmap = i;
bt[i].idCommand = ID_RECTANGLE; // identyfikator przycisku dla rysowania prostokąta
bt[i].iString = i;
i++;
bt[i].dwData = 0;
bt[i].fsState = TBSTATE_ENABLED;
bt[i].fsStyle = TBSTYLE_CHECKGROUP;
bt[i].iBitmap = i;
bt[i].idCommand = ID_SELECT; // identyfikator przycisku dla zaznaczania obiektów
bt[i].iString = i;
toolbar = CreateToolbarEx( // tworzenie toolbar-a
parent_window, // okno rodzica
WS_CHILD|WS_VISIBLE|TBSTYLE_FLAT|TBSTYLE_WRAPABLE, // style: okno potomne; widoczny; płaskie przyciski; przyciski zwijane, gdy nie mogą się zmieścić w oknie programu
TB_ID, // identyfikator toolbar-a
4, // liczba fragmentów wycinanych z bitmapy
hInst, // uchwyt instancji programu
IDB_TB_BITMAP, // identyfikator bitmapy zawartej w zasobach programu
bt, // tablica struktur opisujących przyciski
4, // rozmiar tablicy struktur opisujących przyciski
48, // szerokość przycisku
48, // wysokość przycisku
42, // szerokość bitmapy
42, // wysokość bitmapu
sizeof(TBBUTTON) // rozmiar struktury TBBUTTON
);
SendMessage(toolbar, TB_ADDSTRING, 0, (LPARAM)L"Odcinek Okrąg Prostokąt Zaznaczanie "); // ustawianie tekstu pod obrazkami przycisków toolbar-u
SendMessage(toolbar, TB_AUTOSIZE, NULL, NULL); // automatyczne dostosowanie rozmiaru okna do okna rodzica
// ############################# TWORZENIE STATUS BARU ###############################
statusbar = CreateWindowEx(0, L"msctls_statusbar32",L"",WS_CHILD|WS_VISIBLE, 0, 0, 100, 100, parent_window, (HMENU)SB_ID ,hInst, 0); // pozyskiwanie uchwytu okna
int parts[3]={120,260,-1}; // szerokość poszczególnych pól statusbar-u
SendMessage(statusbar, SB_SETPARTS, 3, (LPARAM)parts); // ustawianie liczby pól oraz ich szerokości
SendMessage(statusbar, SB_SETTEXT, 0, (LPARAM)L"X= "); // ustawienie tekstu w polu pierwszym
SendMessage(statusbar, SB_SETTEXT, 1, (LPARAM)L"Y= "); // ustawienie tekstu w polu drugim
// ####################################################################################
RECT r;
POINT pt;
SendMessage(toolbar,TB_GETRECT,ID_LINE,(LPARAM)&r); // pobieranie prostokąta przycisku o identyfikatorze ID_LINE
// tutaj pozyskuję współrzędne środka przycisku
pt.x = (r.right + r.left) / 2;
pt.y = (r.bottom + r.top) / 2;
// A tutaj wysyłam komunikaty WM_LBUTONDOWN i WM_LBUTTONUP w celu zaznaczenia przycisku o identyfikatorze ID_LINE
SendMessage(toolbar,WM_LBUTTONDOWN,MK_LBUTTON,MAKELONG(pt.x,pt.y));
SendMessage(toolbar,WM_LBUTTONUP,MK_LBUTTON,MAKELONG(pt.x,pt.y));
ShowWindow(parent_window, SW_NORMAL);
UpdateWindow(parent_window);
MSG msg;
while(GetMessage(&msg, 0,0,0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}