Отправляет email-рассылки с помощью сервиса Sendsay

Assembler - Просто и Эффективно.

  Все выпуски  

Assembler - Просто и Эффективно. Глава #9 - Контролы


Assembler

Глава #9 - Контролы

  Контролы (Controls)
Большая часть свойств окна завсит от класса (процедуры обработки сообщений). Для упрощения программирования, в Windows существуют классы, выполняющие наиболее распространенные задачи.
Используются для отображение элементов управления: кнопки, поля ввода, списки и т.д.
   -------------------------------

  Общая информация.
Для использования большинства контролов, нужно создать дочернее окно, указав класс контрола в качестве класса окна.
Младшое слово стиля окна позволяет задать некоторые свойства, специфичные для каждого контрола. Старшое слово (константы ws_) - стандартные свойства, общие для всех окон.
Контролы управляются посылкой им сообщений. Обычно для посылки сообщений используется функция SendMessageA или SendDlgItemMessageA.
При происхождении некоторых событий, контролы посылают окну-родителю сообщения (Notifications): WM_COMMAND, WM_NOTIFY и д.р.
Для того, чтобы пользователь мог осуществлять навигацию при помощи клавиши TAB, контрол должен иметь стиль WS_TABSTOP, и в цикл обработки сообщений должна быть дабавлена ф-ция IsDialogMessage (с.м. пример).
В MSDN: User Interface Design and Development->Windows Controls находится подробная информация об использовании контролов, их стилях, используемых сообщениях и т.д
   -------------------------------

  Размеры/Координаты
Существует два понятия о размере окна:
  • Screen Rect- Общий прямоугольник окна, включая рамку, заголовок окна, полосы прокрутки и т.д. Указывается при создании окна.
  • Client Rect - Прямоугольник, означающий полезную площадь окна.
Для одного и тогоже Client Rect'а при разных настройках Windows нужно указывать разный Screen Rect. Для вычисления необходимого Screen Rect'а на основе Client Rect'а можно использовать функцию AdjustWindowRect.
Также, в настройках системы пользователя может быть указан любой размер шрифта, из- за чего текст в контролах может не соответствовать размеру контрола. Можно решить эту проблему, либо меняя размер контролов в зависимости от размера шрифта, либо ипользвать шрифт фиксированного размера.
Для создания нужного шрифта можно использовать ф-цию CreateFontIndirectA
   -------------------------------

  Пример
Для компиляции примера необходим MASM. Об использовании этого компилятора с.м. главу #8 (asm32.nm.ru - кнопка архив)
.386
 .model flat,stdcall
;используем inc и lib файлы из пакета masm32 (с.м главу #8)
include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
includelib c:\masm32\lib\kernel32.lib
include c:\masm32\include\user32.inc
includelib c:\masm32\lib\user32.lib
include c:\masm32\include\gdi32.inc
includelib c:\masm32\lib\gdi32.lib

;Для более удобной модификации / настройки программы,
;используемые числа объявляем константами.
EditSizeX equ 200 ;длинна Edit контрола
ControlsY equ 20 ;высота контролов
WndSpace equ 5 ;расстояние между контролами
BtnSizeX equ 85 ;длинна кнопки
WndSizeX equ WndSpace*3+EditSizeX+BtnSizeX ;длинна окна
WndSizeY equ WndSpace*2+ControlsY  ;высота окна
ButtonID equ 100 ;ID кнопки
EditID  equ 200 ;ID Edit контрола

 .data
ProgramClassName db 'AnyClassName',0 ;класс основонго окошка
ButtonClassName  db 'Button',0  ;класс контрола - кнопки
EditClassName  db 'Edit',0  ;класс контрола - поля ввода
WindowText db 'Заголовок окна',0
MsgTitle db 'Текст контрола Edit:',0
ButtonText db 'Display Text',0
WndRect RECT<0,0,WndSizeX,WndSizeY> ;Client Rect окна
WClass WNDCLASSEX <>
MsgS MSG <>
hMainWindow dd ?  ;хэндл главного окна
hButton  dd ?  ;хэндл кнопки
hEdit  dd ?  ;хэндл поля ввода
hEditFont dd ?  ;хэндл шрифта поля ввода
hBtnFont dd ?  ;хэндл шрифта кнопки
NCM NONCLIENTMETRICS<>
TextBuffer db 300 dup (?)
  TBS =$-offset TextBuffer
 .code
start:
;получим информацию о системе. нас интересуют используемые шрифты.
 mov NCM.cbSize,sizeof NONCLIENTMETRICS
 invoke SystemParametersInfo,SPI_GETNONCLIENTMETRICS,\
  sizeof NONCLIENTMETRICS, offset NCM,0
;создадим шрифт, высотой ControlsY-2
 mov NCM.lfMessageFont.lfHeight,ControlsY-2
 invoke CreateFontIndirect,offset NCM.lfMessageFont
 mov [hEditFont],eax
;создадим шрифт, высотой ControlsY-4
 mov NCM.lfMessageFont.lfHeight,ControlsY-4
 invoke CreateFontIndirect,offset NCM.lfMessageFont
 mov [hBtnFont],eax

;зарегистрируем класс главного окна (см главу #7)
 mov WClass.cbSize,size WNDCLASSEX
 mov WClass.style,CS_HREDRAW or CS_VREDRAW
 mov WClass.lpfnWndProc,offset MainWindowProc
 mov WClass.cbClsExtra,0
 mov WClass.cbWndExtra,0
 invoke GetModuleHandle,0
 mov WClass.hInstance,eax
 invoke LoadIcon,0,IDI_APPLICATION
 mov WClass.hIcon,eax
 mov WClass.hIconSm,eax
 invoke LoadCursor,0,IDC_ARROW
 mov WClass.hCursor,eax
 mov WClass.hbrBackground,COLOR_WINDOW
 mov WClass.lpszMenuName,0
 mov WClass.lpszClassName,offset ProgramClassName
 invoke RegisterClassEx,offset WClass

;определим размер основного окна, на основе необходимого Client Rect'а
MainWindowstyle="WS_CAPTION" or WS_DLGFRAME or WS_VISIBLE or WS_MINIMIZEBOX or WS_SYSMENU
 invoke AdjustWindowRect,offset WndRect,MainWindowStyle,0
 mov eax,WndRect.right
 sub eax,WndRect.left
 mov ecx,WndRect.bottom
 sub ecx,WndRect.top
;создадим главное окно
 invoke CreateWindowEx,0,offset ProgramClassName,offset WindowText,\
  MainWindowStyle,CW_USEDEFAULT,CW_USEDEFAULT,eax,ecx,\
  0,0,[WClass.hInstance],0
 mov [hMainWindow],eax
;создадим Edit контрол в главном окне
 invoke CreateWindowEx,WS_EX_STATICEDGE,offset EditClassName,0,\
  WS_TABSTOP or WS_CHILD or WS_VISIBLE  or ES_AUTOHSCROLL,\
  WndSpace,WndSpace,EditSizeX,ControlsY,\
  [hMainWindow],EditID,[WClass.hInstance],0
 mov [hEdit],eax
;установим шрифт Edit контрола
 invoke SendMessage,[hEdit],WM_SETFONT,[hEditFont],1
 invoke SetFocus,[hEdit]  ;сделаем его активным

;создадим кнопку в главном окне
 invoke CreateWindowEx,0,offset ButtonClassName,offset ButtonText,\
  WS_TABSTOP or WS_DISABLED or WS_CHILD or WS_VISIBLE,\
  WndSpace*2+EditSizeX,WndSpace,BtnSizeX,ControlsY,\
  [hMainWindow],ButtonID,[WClass.hInstance],0
 mov [hButton],eax
 invoke SendMessage,eax,WM_SETFONT,[hBtnFont],1 ;установим шрифт кнопки

MsgLoop:
 invoke GetMessage,offset MsgS,0,0,0
 inc eax
 jz EndMsgLoop
 dec eax
 jz EndMsgLoop
 invoke IsDialogMessage,[hMainWindow],offset MsgS
 or eax,eax
 jnz MsgLoop
 invoke TranslateMessage,offset MsgS
 invoke DispatchMessage,offset MsgS
 jmp MsgLoop
EndMsgLoop:
 invoke ExitProcess,0

MainWindowProc proc hwnd:dword,uMsg:dword,wParam:dword,lParam:dword
 cmp [uMsg],WM_COMMAND
 jnz NotCommand
;обработка WM_COMMAND
 cmp word ptr [wParam+2],BN_CLICKED
 jnz NotBtnClick
 cmp word ptr [wParam],ButtonID
 jnz CallDefProc
;кнопка ButtonID нажата.
;получим текст Edit контрола hEdit в память TextBuffer размером TBS
 invoke GetWindowText,[hEdit],offset TextBuffer,TBS
;покажем сообщение, текст которого в TextBuffer
 invoke MessageBox,[hwnd],offset TextBuffer,offset MsgTitle,MB_ICONINFORMATION
 invoke SetFocus,[hEdit]
 jmp CallDefProc
NotBtnClick:
 cmp word ptr [wParam+2],EN_UPDATE
 jnz CallDefProc
 cmp word ptr [wParam],EditID
 jnz CallDefProc
;произошли изменения текста в контроле EditID. Получим длинну его текста.
 invoke GetWindowTextLength,[lParam]
 xor ecx,ecx
 or eax,eax
 setnz cl
 invoke EnableWindow,[hButton],ecx ;установим состояние кнопки
NotCommand:

;стандартная часть процедуры обработки сообщений с.м главу #7.
 cmp [uMsg],WM_DESTROY
 jnz NotWmDestroy
 invoke PostQuitMessage,0
 xor eax,eax
 ret
NotWmDestroy:
CallDefProc:
 invoke DefWindowProc,[hwnd],[uMsg],[wParam],[lParam]
 ret
MainWindowProc endp
end start
Чтобы увидеть, как программа меняет размер шрифта в зависимости от размера контролов, измените значение константы ControlsY.
   -------------------------------

  Ресурсы.
Создавать окна и контролы при помощи ф-ции CreateWindowExA удобно для окон:
  • конфигурация которых заранее неопределена (типа MessageBox)
  • содержащих небольшое количество контролов (пример: программа Блокнот).
Для создания окон с большим количеством контролов, имеющих постоянный размер (например, Калькулятор в Windows), удобнее использовать ресурсы.
Также ресурсы могут содержать иконки, курсоры, меню, изображения, и т.д
Об использовании ресурсов будет рассказанно в следующей главе.
   -------------------------------

 Содержание дальнейших выпусков зависит от вас. Будут разъясняться те темы, которые непонятны большинству читателей. Присылайте свои вопросы и предложения по адресу: asm32@nm.ru .
   -------------------------------


Автор рассылки Владимир Пронин. Любое коммерческое использование материалов рассылки без ведома и прямого согласия автора запрещено.
Письма присланные автору рассылки могут быть опубликованы целиком или частично без предварительного уведомления. Если вы не хотите, чтобы ваше письмо было опубликовано укажите это в начале письма.
Перепечатка материалов разрешена только с непосредственной ссылкой на asm32.nm.ru


В избранное