Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming_Windows_95_Part_I.pdf
Скачиваний:
96
Добавлен:
05.06.2014
Размер:
4.61 Mб
Скачать

204

В драйвере дисплея содержатся несколько ранее определенных курсоров мыши, которые могут использоваться в программах. Наиболее типичным курсором является наклонная стрелка, которая называется IDC_ARROW и определяется в заголовочных файлах Windows. Вершина — это конец стрелки. Курсор IDC_CROSS (используемый в приведенных в этой главе программах BLOKOUT) имеет вершину в центре крестообразного шаблона. Курсор IDC_WAIT в виде песочных часов обычно используется программами для индикации того, что они чем-то заняты. Программисты также могут спроектировать свои собственные курсоры (как это делается в главе 9). Курсор, устанавливаемый по умолчанию, для конкретного окна задается при определении структуры класса окна. Например:

wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

Ниже приведены определения терминов, соответствующих вашим действиям над кнопками мыши:

Щелчок — нажатие и отпускание кнопки мыши

Двойной щелчок — двойное быстрое одно за другим нажатие и отпускание кнопки мыши

Перетаскивание — перемещение мыши при нажатой кнопке

На трехкнопочной мыши кнопки называются левой кнопкой, средней кнопкой и правой кнопкой. В связанных с мышью идентификаторах, определенных в заголовочных файлах Windows, используются аббревиатуры LBUTTON, MBUTTON и RBUTTON. Двухкнопочная мышь имеет только левую и правую кнопки. Единственная кнопка однокнопочной мыши является левой.

Сообщения мыши, связанные с рабочей областью окна

В предыдущей главе вы видели, как Windows посылает сообщения клавиатуры только тому окну, которое имеет фокус ввода. Сообщения мыши отличаются: оконная процедура получает сообщения мыши и когда мышь проходит через окно и при щелчке внутри окна, даже если окно неактивно или не имеет фокуса ввода. В Windows для мыши определен набор из 21 сообщения. Однако, 11 из этих сообщений не относятся к рабочей области, и программы для Windows обычно игнорируют их.

Если мышь перемещается по рабочей области окна, оконная процедура получает сообщение WM_MOUSEMOVE. Если кнопка мыши нажимается или отпускается внутри рабочей области окна, оконная процедура получает следующие сообщения:

Кнопка

Нажатие

Отпускание

Нажатие

 

 

 

(Второй щелчок)

Левая WM_LBUTTONDOWN WM_LBUTTONUP Средняя WM_MBUTTONDOWN WM_MBUTTONUP Правая WM_RBUTTONDOWN WM_RBUTTONUP

WM_LBUTTONDBLCLK WM_MBUTTONDBLCLK WM_RBUTTONDBLCLK

Ваша оконная процедура получает сообщения "MBUTTON" только при наличии трехкнопочной мыши и сообщения "RBUTTON" только при наличии двухили трехкнопочной мыши. Оконная процедура получает сообщения "DBLCLK" (двойной щелчок) только в том случае, если класс окна был определен так, чтобы их можно было получать (как описано ниже).

Для всех этих сообщений значение параметра lParam содержит положение мыши. Младшее слово — это координата х, а старшее слово — координата y относительно верхнего левого угла рабочей области окна. Вы можете извлечь координаты х и y из параметра lParam с помощью макросов LOWORD и HIWORD, определенных в заголовочных файлах Windows. Значение параметра wParam показывает состояние кнопок мыши и клавиш <Shift> и <Ctrl>. Вы можете проверить параметр wParam с помощью битовых масок, определенных в заголовочных файлах. Префикс MK означает "клавиша мыши" (mouse key).

MK_LBUTTON

Левая кнопка нажата

MK_MBUTTON

Средняя кнопка нажата

MK_RBUTTON

Правая кнопка нажата

MK_SHIFT

Клавиша <Shift> нажата

MK_CONTROL

Клавиша <Ctrl> нажата

При движении мыши по рабочей области окна, Windows не вырабатывает сообщение WM_MOUSEMOVE для всех возможных положений мыши. Количество сообщений WM_MOUSEMOVE, которые получает ваша программа, зависит от устройства мыши и от скорости, с которой ваша оконная процедура может обрабатывать сообщения о движении мыши. Вы получите хорошее представление о темпе получения сообщений WM_MOUSEMOVE, когда поэкспериментируете с представленной ниже программой CONNECT.

Если вы щелкните левой кнопкой мыши в рабочей области неактивного окна, Windows сделает активным окно, в котором вы произвели щелчок, и затем передаст оконной процедуре сообщение WM_LBUTTONDOWN. Если ваша

205

оконная процедура получает сообщение WM_LBUTTONDOWN, то ваша программа может уверенно считать, что ее окно активно. Однако, ваша оконная процедура может получить сообщение WM_LBUTTONUP, не получив вначале сообщения WM_LBUTTONDOWN. Это может случиться, если кнопка мыши нажимается в одном окне, мышь перемещается в ваше окно, и кнопка отпускается. Аналогично, оконная процедура может получить сообщение WM_LBUTTONDOWN без соответствующего ему сообщения WM_LBUTTONUP, если кнопка мыши отпускается во время нахождения в другом окне.

Из этих правил есть два исключения:

Оконная процедура может "захватить мышь" (capture the mouse) и продолжать получать сообщения мыши, даже если она находится вне рабочей области окна. Позднее в этой главе вы узнаете, как захватить мышь.

Если системное модальное окно сообщений или системное модальное окно диалога находится на экране, никакая другая программа не может получать сообщения мыши. Системные модальные окна сообщений и диалога запрещают переключение на другое окно программы, пока оно активно. (Примером системного модального окна сообщений является окно, которое появляется, когда вы завершаете работу с Windows.)

Простой пример обработки сообщений мыши

Программа CONNECT, приведенная на рис. 6.1, выполняет достаточно простую обработку сообщений мыши, что позволяет вам получить хорошее представление о том, как Windows посылает сообщения мыши вашей программе.

CONNECT.MAK

#-----------------------

# CONNECT.MAK make file

#-----------------------

connect.exe : connect.obj

$(LINKER) $(GUIFLAGS) -OUT:connect.exe connect.obj $(GUILIBS)

connect.obj : connect.c

$(CC) $(CFLAGS) connect.c

CONNECT.C

/*--------------------------------------------------

CONNECT.C -- Connect-the-Dots Mouse Demo Program

(c) Charles Petzold, 1996

--------------------------------------------------*/

#include <windows.h>

#define MAXPOINTS 1000

#define MoveTo(hdc, x, y) MoveToEx(hdc, x, y, NULL)

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

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

{

static char szAppName[] = "Connect";

HWND

hwnd;

MSG

msg;

WNDCLASSEX

wndclass;

wndclass.cbSize

= sizeof(wndclass);

wndclass.style

= CS_HREDRAW | CS_VREDRAW;

wndclass.lpfnWndProc

= WndProc;

wndclass.cbClsExtra

= 0;

wndclass.cbWndExtra

= 0;

wndclass.hInstance

= hInstance;

wndclass.hIcon

= LoadIcon(NULL, IDI_APPLICATION);

wndclass.hCursor

= LoadCursor(NULL, IDC_ARROW);

wndclass.hbrBackground

=(HBRUSH) GetStockObject(WHITE_BRUSH);

wndclass.lpszMenuName

= NULL;

wndclass.lpszClassName

= szAppName;

wndclass.hIconSm

= LoadIcon(NULL, IDI_APPLICATION);

206

RegisterClassEx(&wndclass);

hwnd = CreateWindow(szAppName, "Connect-the-Points Mouse Demo", WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL, hInstance, NULL);

ShowWindow(hwnd, iCmdShow);

UpdateWindow(hwnd);

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

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

static POINT points[MAXPOINTS];

static int

iCount;

HDC

hdc;

PAINTSTRUCT

ps;

int

i, j;

switch(iMsg)

{

case WM_LBUTTONDOWN : iCount = 0;

InvalidateRect(hwnd, NULL, TRUE); return 0;

case WM_MOUSEMOVE :

if(wParam & MK_LBUTTON && iCount < 1000)

{

points[iCount ].x = LOWORD(lParam); points[iCount++].y = HIWORD(lParam);

hdc = GetDC(hwnd);

SetPixel(hdc, LOWORD(lParam), HIWORD(lParam), 0L);

ReleaseDC(hwnd, hdc);

}

return 0;

case WM_LBUTTONUP : InvalidateRect(hwnd, NULL, FALSE); return 0;

case WM_PAINT :

hdc = BeginPaint(hwnd, &ps);

SetCursor(LoadCursor(NULL, IDC_WAIT));

ShowCursor(TRUE);

for(i = 0; i < iCount - 1; i++) for(j = i + 1; j < iCount; j++)

{

MoveTo(hdc, points[i].x, points[i].y);

LineTo(hdc, points[j].x, points[j].y);

}

ShowCursor(FALSE);

207

SetCursor(LoadCursor(NULL, IDC_ARROW));

EndPaint(hwnd, &ps); return 0;

case WM_DESTROY : PostQuitMessage(0); return 0;

}

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

}

Рис. 6.1 Программа CONNECT

Программа CONNECT обрабатывает три сообщения мыши:

WM_LBUTTONDOWN — Программа очищает рабочую область.

WM_MOUSEMOVE — Если левая кнопка мыши нажата, то программа рисует черную точку в рабочей области в текущем положении мыши.

WM_LBUTTONUP — Программа соединяет все точки, нарисованные в рабочей области, друг с другом. Иногда в результате этого получается симпатичный рисунок, а иногда — плотно заполненный клубок. (См.

рис. 6.2.)

Чтобы воспользоваться программой CONNECT, поместите курсор мыши в рабочую область, нажмите левую кнопку, немного подвигайте мышь, и отпустите левую кнопку. Программа CONNECT лучше работает с кривым шаблоном из нескольких точек, который вы можете нарисовать, быстро двигая мышь при нажатой левой кнопке. В программе используется несколько простых функций интерфейса графического устройства (GDI). Функция SetPixel рисует точку размером с один пиксель определенного цвета — в нашем случае черного. (На дисплее с высокой разрешающей способностью, пиксель может быть почти невидим.) Для рисования линий нужны две функции: MoveTo отмечает координаты х и y начала линии, а LineTo рисует линию. (Обратите внимание, что MoveTo определяется как макрос, использующий функцию MoveToEx.)

Если вы перемещаете курсор мыши за пределы рабочей области до того, как отпускаете кнопку, программа CONNECT не соединяет точки между собой, поскольку она не получает сообщения WM_LBUTTONUP. Если вы возвращаете курсор мыши обратно в рабочую область и снова нажимаете левую кнопку, то CONNECT очищает рабочую область. (Если вы хотите продолжить рисование после того, как отпустили кнопку вне рабочей области, то снова нажмите левую кнопку, пока мышь находится вне рабочей области, а затем переместите мышь обратно внутрь.)

Рис. 6.2 Вывод на экран программы CONNECT

CONNECT хранит информацию о максимум 1000 точках. Число линий, которые рисует программа равно:

((P) × (P — 1))/2

где P — это количество точек. При наличии всех 1000 точек, а это почти 500000 линий, на рисование может уйти несколько минут. Поскольку Windows 95 является вытесняющей многозадачной средой, вы можете в это время переключиться на другие программы. Однако, вы ничего не сможете сделать с программой CONNECT (например,

Соседние файлы в предмете Операционные системы