Список всех сообщений windows

Список всех сообщений windows

Вот и наступил исторический момент прощания c легендарным чёрным окном. Мавр сделал своё дело, мавр может уходить. Жаль, так уходит история, хотя с другой стороны пора развиваться дальше.

Старая и новая концепция программирования:

Все программы, которые были написаны вами до этого момента, имели структуру программ под DOS (хотя и назывались они консольными приложениями под Windows). Они использовали традиционный, процедурный подход к программированию. Что это значит? Программа выполнялась последовательно от начала (от первой строки функции main) до конца в предопределенном порядке. Наиболее часто выполняемые блоки программ выделялись в подпрограммы. Налицо последовательное выполнение программы. Продолжим дальше. Во многих операционных системах взаимодействие между системой и программой инициализирует программа. Например, в DOS программа запрашивает разрешение на ввод и вывод данных. Говоря другими словами, не- Windows-программы (программы, написанные без использования архитектуры Windows-приложения) сами вызывают операционную систему. Операционная система не вызывает прикладную программу. В Windows-приложениях все совершенно наоборот: именно система вызывает программу. Этот процесс осуществляется следующим образом: программа ждет, пока не получит сообщение от Windows.

Сообщение — это сигнал от системы о том, что произошло какое-то событие.

Любое событие, происходящее в системе, будь то создание окна или перемещение мыши, сопровождается соответствующим сообщением, которое посылается либо конкретному окну, либо некоторым, либо всем окнам. Иногда одно событие влечет за собой еще несколько событий и сообщений. Например, событие создание окна влечет за собой событие перерисовки окна, акивизации окна, а так же событие создания окна для дочерних окон (кнопок, полей ввода) и так далее. Сообщение передается программе через специальную функцию, вызываемую Windows. После того как сообщение получено, программа ищет функцию-обработчик данного сообщения, если он определен в коде программы, то выполняется его тело, иначе вызывается стандартный Windows-обработчик (стандартная функция обработки события для этого сообщения). После завершения обработки сообщения программа ожидает следующего. Windows может посылать программе сообщения различных типов. Например, каждый раз при щелчке мышью в окне активной программы посылается соответствующее сообщение. Другой тип сообщений посылается, когда необходимо обновить содержимое активного окна. Сообщения посылаются также при нажатии клавиши, если программа ожидает ввода с клавиатуры. Необходимо запомнить одно: по отношению к программе сообщения появляются случайным образом. Вот почему Windows-программы похожи на программы обработки прерываний: невозможно предсказать, какое сообщение может появиться в следующий момент. Естественно всё это вносит коррективы в традиционный, процедурный подход к программированию. Типичная Windows-программа выполняется нелинейно. Невозможно предсказать, какой фрагмент кода будет выполняться через минуту. Это связано с тем, что сообщения приходят в программу абсолютно произвольно. Сообщение характеризуется номером и двумя числовыми параметрами. Номер сообщения должен быть уникальным, по крайней мере, в пределах одного приложения. Чаще всего пользуются мнемоническим обозначением сообщения ( например, WM_CREATE вместо 0x1 ). Список сообщений находится в файле winuser.h. Например, типичная строка из этого файла:

#define WM_PAINT 0x000F

Параметры сообщения носят название wParam и lParam. Значения и смысл этих параметров зависят от конкретного сообщения.

Примеры сообщений :

События мыши:

С мышью связан целый ряд событий и это вполне естественно, так как мышь является незаменимым механизмом для работы в Windows.

Основы работы с Windows API

Основы работы с Windows API — Сообщения Windows

Содержание материала

Сообщения Windows

Человеку, знакомому с Delphi, должна быть ясна схема событийного управления. Программист пишет только код реакции на какое-либо событие, а дальше программа ждёт, когда система сочтёт, что настало время передать управление этому участку кода. Простые программы в Delphi состоят исключительно из методов реакции на события вроде OnCreate, onclick, OnCloseQerry и т. д. Причём событием называется не только событие в обычном смысле этого слова, то есть когда происходит что-то внешнее, но и ситуация, когда событие используется просто для передачи управления основной программе в тех случаях, когда VCL не может сама справиться с какой-то задачей. Примером такого события является, например, TListBox.OnDrawItem. Устанавливая стиль списка в lbOwnerDrawFixed или lbOwnerDrawVariable, программист как бы сообщает VCL, что он не доволен теми средствами рисования элементов списка, которыми она располагает, и что он берёт эту часть задачи на себя. И каждый раз, когда возникает необходимость в рисовании элемента, VCL передаёт управление специально написанному коду. На самом деле разница между двумя типами событий весьма условна. Можно так же сказать, что когда пользователь нажимает клавишу, VCL не знает, что делать, и поэтому передаёт управление обработчику OnKeyPress.

Читайте также:  Загрузить minecraft java edition для windows

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

В Delphi для реакции на каждое событие обычно создаётся свой метод. В Windows одна процедура, называемая оконной, обрабатывает все сообщения. В языке Си нет понятия , поэтому при использовании Паскаля может возникнуть путаница. Дело в том, что то, что называется оконной процедурой, на самом деле является функцией. Тем не менее, я буду использовать общепринятый термин . Каждое сообщение имеет свой уникальный номер, а оконная процедура обычно целиком состоит из оператора case, и каждому сообщению соответствует своя альтернатива этого оператора. Номера сообщений учить не надо, потому что можно использовать константы, описанные в модуле Messages.dcu. Эти константы начинаются с префикса, указывающего на принадлежность сообщения к какой-то группе. Например, сообщения общего назначения начинаются с WM_: например, WM_Paint, WM_GetTextLength. Сообщения, специфичные, например, для кнопок, начинаются с префикса BM_. Остальные группы сообщений также связаны либо с теми или иными элементами управления, либо со специальными действиями, например, с динамическим обменом данными (dynamic data exchange, DDE). Обычной программе приходится обрабатывать довольно много сообщений, поэтому оконная процедура бывает, как правило, очень длинной и громоздкой. Оконная процедура описывается программистом как callback функция и указывается при создании оконного класса. Таким образом все окна данного класса имеют одну и ту же оконную процедуру. Впрочем, существует возможность породить так называемый подкласс, то есть новый класс, наследующий все свойства существующего, за исключением оконной процедуры. Несколько подробнее об этом будет сказано далее.

Кроме номера, каждое сообщение содержит два параметра — WParam и LParam. Буквы и означают и , то есть первый параметр 16-разрядный, а второй — 32-разрядный. Однако так было только в старых, 16-разрядных версиях Windows. В 32-разрядных версиях оба параметра 32-разрядные, несмотря на их названия. Конкретный смысл каждого параметра зависит от сообщения. В некоторых сообщениях один или оба параметра могут вообще не использоваться, в других — наоборот, двух параметров даже не хватает. В этом случае один из параметров (обычно LParam) содержит указатель на дополнительные данные. После обработки сообщения оконная процедура должна вернуть какое-то значение. Обычно это значение просто сигнализирует, что сообщение не нуждается в дополнительной обработке, но в некоторых случаях оно более осмысленно, например, WM_SetIcon должно вернуть дескриптор иконки, которая была установлена ранее. Если программист не хочет обрабатывать сообщение самостоятельно, он должен вызвать для его обра-ботки функцию DefWindowProc.

Обработка сообщения требует времени, иногда довольно значительного. За это время окну может быть отправлено ещё несколько сообщений. Чтобы они не пропали, Windows организует так называемую очередь сообщений. Очередь сообщений своя для каждой нити. Нить должна сама выбирать сообщения из этой очереди, транслировать их и затем вызывать функцию Dispatch-Message, чтобы направить это сообщение в нужную оконную процедуру. Всё это лучше не писать самому, а оставить на совести VCL, которая прекрасно с этим справляется. При программировании в Delphi обычно требуется либо нестандартная реакция на сообщение, либо отправка сообщения другому окну.

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

Кроме параметров WParam и LParam, каждому сообщению приписывается время возникновения и координаты курсора в момент возникновения. Эти параметры можно узнать с помощью функций GetMessagePos и GetMessageTime.

Сообщения Windows и их обработка (исходники)

Что же такое «Сообщение Windows»? Этот вопрос первым может возникнуть у начинающего программиста, тот же, кто когда-либо сталкивался с этим, хитро ухмыльнется и спрячет свои мысли в загадочную улыбку.

Взаимодействие, как форма общения

В своей повседневной жизни, мы постоянно общаемся. Общение может подразумевать разговор, совместную работу и еще много всего прочего, однако в любом случае это обмен разного рода информацией, выраженной различными формами взаимодействия. Так же происходит и в электронном мире, когда мы запускаем какую-нибудь программу, не важно игра это, текстовый редактор, или среда разработки Delphi. Программы, начинают, скрыто от нас общаться и обмениваться информацией, в простейшем виде это обмен информацией между операционной системой и приложением.

Читайте также:  How to change the window color on windows 10

Приложение может взаимодействовать, как со своими дочерними формами, так и с «посторонними» (внешними) приложениями. Виды взаимодействия с внешними приложениями могут быть следующими:

  • непосредственный запуск внешней программы из высшего приложения
  • запуск внешней программы, связанной с некоторым документом
  • обмен сообщениями с другими программами
  • технология OLE — внедрения и связывания документов, подготовленных внешними программами, в ваше приложение
  • управление внешними программами как серверами
  • динамический обмен данными между приложениями.

В данной статье нам предстоит познакомиться с сообщениями и способами их обработки.

Обработка сообщений в приложениях Windows

И все же что такое сообщение? Как оно выглядит? Как можно его послать? Немного терпения друзья мои, и Вы все узнаете.

Итак! Настал момент выложить карты на стол. В свое время сообщения выглядели крайне не приветливо, и было довольно сложно для запоминания В новых версиях Windows, великая и могучая и всеми «любимая» Microsoft, видимо осознав все это значительно облегчила Нам жизнь, приведя сообщения к вполне «цивилизованному» виду (например WM_CLOSE ).

Рассмотрим некоторые виды сообщений:

WM_CLOSE — сигнализирует, что окно или приложение закрывается. Это сообщение не имеет параметров. По умолчанию оно закрывает окно, которому послано. Если приложение обрабатывает это сообщение, то оно должно возвращать нуль. При обработке этого сообщение приложение может запросить пользователя о необходимости закрывать окно или вызвать функцию закрывания окна только при положительном ответе.

WM_ACTIVATE — посылается, когда окно переводится в активное или неактивное состояние. Сначала сообщение посылается окну, переходящему в неактивное состояние, а потом — активируемому. Это сообщение имеет дополнительные параметры:

fActive = LOWORD(wParam); Флаг активации
fMinimized = (BOOL) HIWORD(wParam); Флаг минимизации (1 — если окно минимизировано, 0 — если нет)
hwndPrevious = (HWND) lParam; Идентификатор окна (Handle)

Параметр fActive показывает, как активизируется или деактивируется окно. Возможные значения этого параметра:

WA_ACTIVE окно активизируется не щелчком мыши (например, функцией SetActiveWindow или клавиатурой)
WA_CLICKACTIVE окно активизируется щелчком мыши
WA_INACTIVE окно деактивируется

Параметр hwndPrevious — это дескриптор, который указывает на окно, из которого фокус переключился на данное окно, если оно активируется, или на окно, в которое передается управление, если данное окно деактивируется. По умолчанию, если активируемое окно не свернуто, то оно получает фокус. Если приложение обрабатывает это сообщение, то оно должно возвращать нуль.

WM_GETMINMAXINFO — посылается при изменении размеров или положения окна. Обработчик события может использоваться для ограничения допустимых размеров и координат положения на экране.

WM_GETMINMAXINFO
lpmmi = (LPMINMAXINFO) lParam; // address of structure

Параметр lpmmi указывает на структуру типа MINMAXINFO, содержащую принятые по умолчанию пределы изменения размеров и координат положения окна. Описание этой структуры:

typedef struct tagMINMAXINFO < // mmi
POINT ptReserved;
POINT ptMaxSize;
POINT ptMaxPosition;
POINT ptMinTrackSize;
POINT ptMaxTrackSize;
> MINMAXINFO;

Поля структуры означают следующее:

ptReserved Зарезервировано и пока не используется
ptMaxSize Поле типа Point определяет ширину (Point.x) и высоту (Point.y) развернутого окна
ptMaxPosition Поле типа Point определяет положение левого (Point.x) и верхнего (Point.y) краев развернутого окна
ptMinTrackSize Поле типа Point определяет минимальную ширину (Point.x) и минимальную высоту (Point.y) окна при изменении пользователем размеров его рамки.
ptMaxTrackSize Поле типа Point определяет максимальную ширину (Point.x) и максимальную высоту (Point.y) окна при изменении пользователем размеров его рамки.

Если приложение обрабатывает это сообщение, оно должно вернуть 0.

WM_COPYDATA — посылается, когда одно приложение передает данные другому приложению.
Определение:
WM_COPYDATA

wParam = (WPARAM) (HWND) hwnd; Дескриптор посылающего окна
lParam = (LPARAM) (PCOPYDATASTRUCT) pcds; указатель на структуру с данными

Параметр hwnd идентифицирует окно, посылающее данные.
Параметр pcds указывает на структуру типа COPYDATASTRUCT, содержащую пересылаемые данные. Описание этой структуры:

typedef struct tagCOPYDATASTRUCT

< cds DWORD dwData; до 32 бит данных, передаваемых приложению-получателю
DWORD cbData; определяет размер (в байтах) даных, на которые указывает lpData
PVOID lpData; указатель на данные, передаваемые приложению-получателю
> COPYDATASTRUCT;

Возвращаемое приложение-приемник обрабатывает сообщение, оно должно возвратить значение TRUE; в противном случае — FALSE.

  • При посылке сообщения приложение должно использовать функцию SendMessage, использование PostMessage не допускается.
  • Посылаемые данные не должны содержать указателей или других ссылок на объекты, недоступные для приложения, получающего данные.
  • Пока посылается сообщение, посылаемые данные не должны изменяться другим потоком посылающего процесса.
  • Приложение, получающее данные, рассматривает их как данные только для чтения.
  • Параметр pcds действует только в процессе приема сообщения. Приложение, получающее данные, не может освобождать память, на которую ссылается pcds.
  • Если приложение, получающее данные, должно иметь к ним доступ после завершения процедуры SendMessage, оно должно скопировать данные в локальный буфер.

Посылка сообщений

Функция SendMessage посылает указанное в ней сообщение окну или множеству окон и не возвращается, пока это сообщение обрабатывается. Этим она отличается от функции PostMessage , которая возвращается сразу после передачи сообщения.

Объявление функции:
function SendMessage(HWND: hWnd, Msg,WPARAM: word,LPARAM: longint):longint;

Параметр hWnd — дескриптор окна, которому передается сообщение.
Параметр Msg определяет передаваемое сообщение. Параметры WPARAM и LPARAM могут содержать дополнительную информацию. Значение, возвращаемое функцией, зависит от вида сообщения.

Функция PostMessage не годится для передачи срочных сообщений, но зато она не блокирует вызвавшее приложение на время обработки сообщения приемником. Объявление функции:

function PostMessage(HWND: hWnd, Msg,WPARAM: word,LPARAM: longint):longint;

Параметр hWnd — дескриптор окна, которому передается сообщение. Если этот параметр nil, то сообщение становится в очередь сообщений (если она есть) текущего процесса.
Параметр Msg определяет передаваемое сообщение. Параметры WPARAM и LPARAM могут содержать дополнительную информацию. Функция возвращает ненулевое значение при успешном завершении и нуль в случае аварийного завершения. В этом случае причину ошибки можно установить вызовом функции GetLastError.

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

SendMessage (Form2.Handle, WM_CLOSE, 0, 0);

В данной строке ясно видно, что мы работаем с дочерним окном своего приложения (Form2.Handle) и передаем ему «приказ» закрыться (WM_CLOSE).

var
CDS : TCopyDataStruct;
dt : TDateTime;
ms : TMemoryStatus;
begin
.
GlobalMemoryStatus(ms);
CDS.dwData:=ms.dwAvailPageFile+ms.dwAvailPhys;
CDS.cbData:=SizeOf(dt);
CDS.lpData:=@dt;
SendMessage(FindWindow (`TForm1`, `Form1`), WM_COPYDATA, 0, longint(@CDS));
.
end;

Очевидно, что мы посылаем найденному окну внешней программы (в нашем случае заголовок окна будет иметь значение Caption = `Form1`) сообщение с дополнительными параметрами, опять же в нашем случае это адрес структуры CDS типа TcopyDataStruct (longint(@CDS)), в которую мы предварительно занесли информацию о текущем времени и объеме свободной памяти.

Замечание : здесь стоит сразу оговориться, что если процедура FindWindow будет иметь вид FindWindow (`TForm1`, nil ), то сообщение будет отослано всем приложениям, имеющим в своем составе класс TForm1, т.к эта запись предполагает любое значение свойства Caption в заголовке.

Во всех оконных компонентах предусмотрены обработчики сообщений Windows по умолчанию. Можно определить свои собственные обработчики, заменив ими обработчики по умолчанию, или дополнив их. Объявление своего обработчика помещается в описание класса оконного компонента, как правило, в раздел private. Синтаксис объявления:

procedure (var : ); message ;

Здесь обозначает имя процедуры обработки сообщения. Имя может быть любым, но обычно принято делать его тождественным имени обрабатываемого сообщения, исключив из него символ подчеркивания. Передаваемый в обработчик параметр также может иметь любое имя. Этот параметр представляет собой запись, через которую в обработчик передаются параметры сообщения, а из обработчика возвращается значение поля Result, фиксирующее результат обработки. — это тип структуры параметров сообщения. После ключевого слова message записывается тип сообщения.

Снова обратимся к демонстрационной программе и посмотрим пример объявления своего обработчика сообщения WM_CLOSE:

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
private
< Private declarations >
procedure WMClose(var a : TWMClose) ;message WM_CLOSE;
.
implementation
<$R *.dfm>
.
procedure TForm2.WMClose( var a:TWMClose);
begin
if MessageDlgPos(`Меня хотят закрыть. Согласны?`, mtConfirmation, [mbYes,mbNo],0,BoundsRect.Left,BoundsRect.Bottom)=mrYes then Close
else Label1.Caption:=`Не закроюсь!`;
end;

Здесь мы объясняем программе, как нужно реагировать на сообщение операционной системы о том, что ей пора закрываться. При попытке ее закрыть, она будет оказывать сопротивление и спросит Вас действительно ли ей нужно закрыться, или нет.

Определение собственных сообщений

Можно описать свои собственные сообщения, и работать с ними так же, как и с предопределенными API Windows.
Номера своих собственных сообщений необходимо отсчитывать от константы WM_USER, которая соответствует первому номеру сообщения пользователя.
Например, можно определить в своем приложении константы

Const
WM_MyMess1=WM_USER;
WM_MyMess2=WM_USER+1;

и затем оперировать с сообщениями WM_MyMess1 и WM_MyMess2 как с предопределенными в Windows.
Ниже представлен пример объявления своего сообщения:
.
private
< Private declarations >
procedure WMin ( var b : TMessage); message WM_USER ;
.
procedure TForm2.WMin ( var b : TMessage);
begin
Form2.WindowState := wsMinimized;
end;

Вот и закончилось наше путешествие в мир сообщений Windows, как заканчивается очередная глава, понравившейся книги. В данной статье я постарался сообщить Вам по этой теме все, что знаю я, и буду рад, если хоть кому-то она пойдет впрок. Помните господа, Вы программисты! У вас особый склад ума и особый статус! И не важно, на каком Вы уровне и сколько на данный момент у Вас знаний; важно постоянно совершенствовать себя и давать для этого возможность другим, быть чуткими к близким и не размениваться по мелочам. Покорно благодарю всех, кто почтил внимаем сей скромный труд и дочитал до этих строк, растите в профессиональном плане и любите Linux.

Читайте также:  Create keytab file linux
Оцените статью