Шаблон ассемблерного оконного приложения

Дата публикации 14 июн 2002

Шаблон ассемблерного оконного приложения — Архив WASM.RU

  Каждый сайт, хоть немного причастный к программированию для Windows, считает своим долгом поместить на своих страницах шаблон оконного приложения. Assembler.ru в этом отношении ничем не хуже остальных. Почему бы и нет? Это настоящее, живое, работающее приложение, чего ж его стыдиться? Многим из нас его хватит, чтобы сказать себе с удовлетворением: "Достаточно, я в себя поверил", и вернуться к любимому третьему видеорежиму. Остальным же, возможно, оно понадобится еще много-много раз для того, чтобы начать с него новый проект, и, потратив полмесяца на его развитие, выяснить, что нужно было начинать с чего-то другого. Итак:

Код (Text):
  1.  
  2. .386
  3. .Model flat,stdcall
  4.  
  5. ;заголовочный файл API;
  6. ;////////////////////////////////////////////////////// windows.inc
  7. GetModuleHandleA  PROTO :DWORD               ;прототипы функций API
  8. LoadIconA         PROTO :DWORD,:DWORD
  9. LoadCursorA       PROTO :DWORD,:DWORD
  10. RegisterClassExA  PROTO :DWORD
  11. CreateWindowExA   PROTO :DWORD,:DWORD,:DWORD,:DWORD,\
  12.                         :DWORD,:DWORD,:DWORD,:DWORD,\
  13.                         :DWORD,:DWORD,:DWORD,:DWORD
  14. ShowWindow        PROTO :DWORD,:DWORD
  15. GetMessageA       PROTO :DWORD,:DWORD,:DWORD,:DWORD
  16. TranslateMessage  PROTO :DWORD
  17. DispatchMessageA  PROTO :DWORD
  18. ExitProcess       PROTO :DWORD
  19. PostQuitMessage   PROTO :DWORD
  20. DefWindowProcA    PROTO :DWORD,:DWORD,:DWORD,:DWORD
  21.  
  22. WNDCLASSEXA STRUCT 8                         ;структура класса окна
  23.   cbSize          dd ?
  24.   style           dd ?
  25.   lpfnWndProc     dd ?
  26.   cbClsExtra      dd ?
  27.   cbWndExtra      dd ?
  28.   hInstance       dd ?
  29.   hIcon           dd ?
  30.   hCursor         dd ?
  31.   hbrBackground   dd ?
  32.   lpszMenuName    dd ?
  33.   lpszClassName   dd ?
  34.   hIconSm         dd ?
  35. WNDCLASSEXA ENDS
  36.  
  37. POINT STRUCT 8
  38.   x               dd ?
  39.   y               dd ?
  40. POINT ENDS
  41.  
  42. MSG STRUCT 8                                 ;структура сообщения
  43.   hwnd            dd ?
  44.   message         dd ?
  45.   wParam          dd ?
  46.   lParam          dd ?
  47.   time            dd ?
  48.  
  49.   pt              POINT{}
  50. MSG ENDS
  51.  
  52. NULL              =0                         ;разные константы
  53. IDI_APPLICATION   =32512
  54. IDC_ARROW         =32512
  55. COLOR_WINDOWFRAME =6
  56. SW_SHOW           =5
  57. EXIT_ERROR        =0ffffffffh
  58. WM_DESTROY        =2
  59.  
  60. CS_VREDRAW        =0001h
  61. CS_HREDRAW        =0002h
  62.  
  63. WS_OVERLAPPED     =00000000h                 ;константы стилей окна
  64. WS_CAPTION        =00C00000h
  65. WS_SYSMENU        =00080000h
  66. WS_THICKFRAME     =00040000h
  67. WS_MINIMIZEBOX    =00020000h
  68. WS_MAXIMIZEBOX    =00010000h
  69.  
  70. WS_OVERLAPPEDWINDOW=WS_OVERLAPPED OR\
  71.                     WS_CAPTION OR\
  72.                     WS_SYSMENU OR\
  73.                     WS_THICKFRAME OR\
  74.                     WS_MINIMIZEBOX OR\
  75.                     WS_MAXIMIZEBOX
  76.  
  77. ;///////////////////////////////////////////////////////// WinMain
  78. .const
  79.     app_name      db "WinApp Template",0            ;имя приложения
  80.     class_name    db "WinApp Template Class",0      ;имя класса окна
  81. .data?
  82.     win_class     WNDCLASSEXA{}
  83.     win_handle    dd ?
  84.     loop_message  MSG{}
  85. .code
  86. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  87. WinMain PROC PUBLIC hinst,prev_hinst,command_line,cmd_show
  88. ;................................ регистрация класса окна
  89.   mov win_class.cbSize,sizeof(WNDCLASSEXA)
  90.   mov win_class.style,CS_HREDRAW OR CS_VREDRAW
  91.   mov win_class.lpfnWndProc,offset win_procedure
  92.   mov win_class.cbClsExtra,0
  93.   mov win_class.cbWndExtra,0
  94.   invoke GetModuleHandleA,NULL
  95.   mov win_class.hInstance,eax
  96.   invoke LoadIconA,NULL,IDI_APPLICATION
  97.   mov win_class.hIcon,eax
  98.   mov win_class.hIconSm,eax
  99.   invoke LoadCursorA,NULL,IDC_ARROW
  100.   mov win_class.hCursor,NULL
  101.   mov win_class.hbrBackground,COLOR_WINDOWFRAME
  102.   mov win_class.lpszMenuName,NULL
  103.   mov win_class.lpszClassName,offset class_name
  104.   invoke RegisterClassExA,offset win_class
  105.   .if(!eax)
  106.     jmp abort
  107.   .endif
  108. ;........................................... создание окна
  109.   invoke CreateWindowExA,NULL,\
  110.                          offset class_name,\
  111.                          offset app_name,\
  112.                          WS_OVERLAPPEDWINDOW,\
  113.                          100,100,300,200,\
  114.                          NULL,\
  115.                          NULL,\
  116.                          win_class.hInstance,\
  117.                          NULL
  118.   .if(!eax)
  119.     jmp abort
  120.   .endif
  121.   mov win_handle,eax           ;он еще пригодится, только не сегодня
  122. ;............................................ вывод окна на экран
  123.   invoke ShowWindow,eax,SW_SHOW
  124. ;............................................ инициализация
  125. ;здесь можно вставить все необходимые действия для первичной инициализации
  126. ;приложения (например, загрузку и разбор файла настроек)
  127. ;............................................ цикл опроса очереди сообщений
  128. msg_loop:
  129.   invoke GetMessageA,offset loop_message,NULL,0,0
  130.   .if(!eax)
  131.     invoke ExitProcess,loop_message.wParam   ;успешное завершение приложения
  132.   .endif
  133.   invoke TranslateMessage,offset loop_message
  134.   invoke DispatchMessageA,offset loop_message
  135.   jmp msg_loop
  136. ;............................................. аварийное завершение
  137. abort:
  138.   invoke ExitProcess,EXIT_ERROR
  139. WinMain ENDP
  140.  
  141. ;///////////////////////////////////////////// Оконная процедура
  142. win_procedure PROC window_from,message,w_param,l_param
  143.   .if(message==WM_DESTROY)
  144.     invoke PostQuitMessage,0
  145. ; .elseif(message==...)      ;обработка остальных необходимых сообщений
  146. ;   ...
  147. ; .elseif(message==...)
  148. ;   ...
  149. ; .elseif(message==...)
  150. ;   ...
  151.   .else                      ;сообщение не обработано
  152.     invoke DefWindowProcA,window_from,message,w_param,l_param
  153.     ret
  154.   .endif
  155.   xor eax,eax                ;сообщение обработано
  156.   ret
  157. win_procedure ENDP
  158.  
  159. ;#############################################################
  160. end
  161.  
  162.  
  163.  

  Вот, собственно, и все приложение. В нем реализованы фундаментальные концепции общего прикладного програмирования для Windows:

  • работа начинается с вынужденного объектно-ориентированного действия - громоздкой регистрации класса окна с помощью функции RegisterClassExA. Вы должны сделать это, даже если собираетесь создать всего одно окно с такими свойствами, потому что так повелел когда-то Уильям Гейтс Второй, известный в народе как просто Билл. Впрочем, вы можете избежать этой неприятной процедуры, если воспользуетесь при создании окна одним из предопределенных классов - BUTTON, COMBOBOX , EDIT , LISTBOX , MDICLIENT , SCROLLBAR , STATIC. С помощью, например, класса BUTTON вы можете сделать большую-пребольшую кнопку и нажимать ее день и ночь до умопомрачения, ожидая, пока из floppy-дисковода выскочит банан. А класс STATIC очень удобен для эмуляции забора: написанное на таком окне емкое трехбуквенное слово всегда напомнит вам о необходимости вернуться к повседневным заботам.
  • если регистрация класса окна прошла успешно, можно создать само окно с помощью функции CreateWindowExA. Полученный при ее возврате в регистре eax дескриптор окна следует сохранить до лучших времен. Он потребуется очень часто для выполнения манипуляций с окном.
  • созданное окно полностью функционально за исключением одной мелочи: его не видно. Может, и в самом деле его не стоит показывать, чтобы не позориться. А иногда это действительно не нужно, например, если использовать главное окно для общей диспетчеризации приложения, а для общения с пользователем создавать другие окна. Но если вам действительно нужно показать окно, то это делает функция ShowWindow
  • следующий этап - ваш. Делайте что хотите. Можете пойти попить кофейку, а можете чего-нибудь попрограммировать. Но помните: пока еще в приложении обработка сообщений не идет, поэтому оно мертво. Свежесозданное окно торчит недвижимо на экране как символ стабильности внутриполитических процессов, и ничто не оставляет на нем следов, как на зубах Кристины Пугачевой/Орбакайте/Пресняковой/Орбакайте.
  • и только цикл опроса очереди сообщений оживит ваше окно, и кнопочки в его заголовке начнут нажиматься, вызывая разные полезные эффекты, и границы его станут послушны движениям придавленной слева мыши, и много еще чего разного можно будет сделать с этим окном.
  • потому что в вашем распоряжении теперь - оконная процедура win_procedure. Она принимает все и всяческие сообщения, адресуемые вашему окну всеми, кому не лень, и делает в ответ на них все, что вы пожелаете. В данном случае вы пожелали отправлять все эти сообщения обратно в систему, чтобы она сама делала с окном то, что повелел когда-то Билл. Единственное сообщение, на которое реагирует ваша оконная процедура - это WM_DESTROY, которое означает, что вам надоело любоваться окном, и вы нажали Alt+F4, или щелкнули по кнопочке с крестиком, или выбрали Close в системном меню. Да и поделом ему.
Если вы соберетесь откомпилировать приложение, вы можете сделать это с помощью MS Developer Studio, воспользовавшись нашими рекомендациями.
© Svet(R)off

1 4.131
archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532

Комментарии


      1. eroha 12 июн 2017