4.1.9. ПРИМЕР РАБОТЫ С КИСТЬЮ

Для  демонстрации обработки сообщения  WM_LBUTTONDOWN , поступающего при нажатии левой кнопки мыши, разработаем программу, выводящую на экран компьютера кустарник, состоящий из отдельных кустов. При каждом нажатии левой кнопки мыши она будет выводить куст, корень которого находится в позиции, указанной курсором мыши. Листья кустарника будем изображать зеленым цветом, с помощью функции Ellipse(). Поскольку внутренние точки эллипса окрашиваются цветом кисти, то необходимо определить кисть. Для этого вызовем функции

     

Hgreenbrush     = CreateSolidBrush (RGB(0,255,0));

hbrush    = SelectObject (hdc,hgreenbrush);

возвращающие значения, определенные с помощью

           

HBRUSH hgreenbrush,hbrush;

где  hdc   – контекст устройства.

Цвет шаблона восстанавливается с помощью вызова функции

SelectObject(hdc,hbrush);

            Разработаем рекурсивную подпрограмму, выводящую на экран куст,  состоящий из ствола, веток и  листьев (рис. 2.9). Из конца каждой ветки (и из конца ствола) выходят две ветки, углы между которыми и длины которых вычисляются случайным образом (рис. 2.10). Рекурсивная функция будет иметь следующий прототип:

            void tree (HDC dc, float x, float y, float l, float phi);

где dc – контекст устройства, (х,у) – координаты начала ветки, l – длина ветки, phi – угол между веткой и осью абсцисс.

Рис. 2.9. Куст

Рис. 2.10. Ветка

Эта функция выводит отрезок длины l, соединяющий точки (x,y) и                    (x+lcos, y+lsin), а потом вызывает себя два раза, передавая параметры таким образом, что при первом вызове рисуется ветка длины rn(l)*0.8, под углом+rn(/50), а при втором  — длины rn(l)*0.8 под углом-rn(/50). Здесь rn(x) – функция, значениями которой являются случайные числа t, равномерно распределённые в интервале . Когда длина ветки не превышает одного пиксела, то выводится лист  ( круг радиуса 5).

Программа

#include <windows.h>

#include <string.h>

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#include <math.h>

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

char szwinname[] = "MyWindow";

int maxX,maxY;

int i=0;

POINT pnts[4];

HDC memdc;

HBITMAP hbit;

int WINAPI WinMain(HINSTANCE hthisinst, HINSTANCE hprevinst,

                                    LPSTR lpszargs, int nwinmode)

{

 HWND hwnd;

 MSG msg;

 WNDCLASS wcl;

 HACCEL haccel;

 wcl.hInstance = hthisinst;

 wcl.lpszClassName = szwinname;

 wcl.lpfnWndProc= WindowFunc;

 wcl.style = 0;

 wcl.hIcon = LoadIcon (NULL, IDI_APPLICATION);

 wcl.hCursor = LoadCursor(NULL,IDC_ARROW);

 wcl.lpszMenuName = NULL;

 wcl.cbClsExtra = 0;

 wcl.cbWndExtra = 0;

 wcl.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

       if(!RegisterClass(&wcl)) return 0;

       hwnd = CreateWindow(szwinname, "Tree",

        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT, 600, 600,

        HWND_DESKTOP, NULL, hthisinst, NULL);

              haccel=LoadAccelerators(hthisinst,NULL);

        ShowWindow(hwnd,nwinmode);

              UpdateWindow(hwnd);

       SetTimer(hwnd,1,30,NULL);

              while(GetMessage(&msg,NULL,0,0))

        {

             if(!TranslateAccelerator(hwnd,haccel,&msg))

             {

                   TranslateMessage(&msg);

                   DispatchMessage(&msg);

             }

        }

KillTimer(hwnd,1);

       return msg.wParam;

}

// генерация случайного числа из отрезка (0.5x, x)

float rn(float x)

{

return x*(500.+rand()%500)/1000;

}

// рекурсивная функция вывода дерева

void tree(HDC dc,float x, float y, float l, float phi)

{

if(l<=1) Ellipse(dc,x-5,y-5,x+5,y+5);// вывод листа

else

{

       MoveToEx(dc,x,y,NULL);

   LineTo(dc,x+l*cos(phi), y+l*sin(phi));// вывод ветки

   tree(dc,x+l*cos(phi), y+l*sin(phi),rn(l)*0.8, phi+rn(3.14/5));

   tree(dc,x+l*cos(phi), y+l*sin(phi),rn(l)*0.9, phi-rn(3.14/5));

}

}

LRESULT CALLBACK WindowFunc(HWND hwnd,

                                    UINT message,

                                    WPARAM wParam,

                                    LPARAM lParam)

{

static HDC hdc;

double phi;

double r=100;

static HBRUSH hbrush;

static HBRUSH hgreenbrush;

switch(message)

{

       case WM_CREATE:

             maxX= 600;

             maxY= 600;

             hdc = GetDC (hwnd);

             hgreenbrush = CreateSolidBrush(RGB(0,255,0));

             hbrush = (HBRUSH)SelectObject(hdc, hgreenbrush);

             break;

      case WM_LBUTTONDOWN:

             randomize();

             tree(hdc,LOWORD(lParam) ,HIWORD(lParam),

                         (0.+maxY)/5, -3.14/2);

      break;

       case WM_DESTROY:

             SelectObject(hdc, hbrush);

             ReleaseDC(hwnd,hdc);

         DeleteObject(hgreenbrush);

             DeleteObject(hbrush);

             PostQuitMessage(0);

             break;

       default:

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

}

return 0;

}

Результаты работы программы приведены на рис. 2.11.

Рис. 2.11. Кустарник