Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 2 138

/ вопрос открыт /

Здравствуйте!
Есть вопрос по winapi и непосредственно по языку delphi. Я написал класс для работы с Winapi окнами, он создаёт, удаляет окно, обрабатывает сообщения. С последним как раз и есть проблема.
При создании окна через CreateWindowEx WindowClass.lpfnwndproc присваеватся адрес функции WinProc (обработчик сообщений). Сейчас я написал эту функцию вне класса, но в этом модуле. Так как нужно создавать не один объект окна, то всё окна будут обращаться к одной функции и будет путанница. Если функцию делать внутри класса, то выдаёт ошибку.
Собственно сам вопрос : Как записать функцию внутри класса и использовать её как обработчик сообщений?

Приложение:
  1.  
  2.  
  3. unit uVEWindows;
  4.  
  5. interface
  6.  
  7. uses
  8. Windows,
  9. Classes,
  10. Messages,
  11. SysUtils,
  12. uVETypes,
  13. uVESettings;
  14.  
  15. type
  16. TVEApiWindow = class
  17. private
  18. fHandle : HWND;
  19. fHinstance : Cardinal;
  20. fWindowClass: TWndClassex;
  21. fmmsg: tagMsg;
  22. fKeyState : TKeyState;
  23. fOnMessage, fOnRestore, fOnPaint, fOnResize, fOnProcces : TVEEvent;
  24. fOnKeyPress : TVEKeyPress;
  25. fWinProc : TVEWMProc;
  26. fTitle : String;
  27. fVisibled, fActive, fExit : Boolean;
  28. function GetWindowClass: PWndClassex;
  29. procedure SetWindowClass(const Value: PWndClassex);
  30. procedure SetOnKeyPress(const Value: TVEKeyPress);
  31. procedure SetOnMessage(const Value: TVEEvent);
  32. procedure SetOnPaint(const Value: TVEEvent);
  33. procedure SetOnResize(const Value: TVEEvent);
  34. procedure SetOnRestore(const Value: TVEEvent);
  35. function GetKeyState: PKeyState;
  36. procedure SetKeyState(const Value: PKeyState);
  37. function GetDisplaySettings: PVEDisplaySettings;
  38. procedure SetDisplaySettings(const Value: PVEDisplaySettings);
  39. procedure SetTitle(const Value: String);
  40. public
  41. constructor Create;
  42. destructor Destroy; override;
  43. procedure CreateWindow;
  44. procedure FreeWindow;
  45.  
  46. function GetWindowMsg : LongBool;
  47. procedure WindowMsgProc;
  48. function ProcessMessages : Boolean;
  49.  
  50. procedure Show;
  51. procedure Hide;
  52.  
  53. procedure UpdateWindow;
  54. procedure ReCreate;
  55.  
  56. property Handle : HWND read fHandle;
  57. property WindowClass : PWndClassex read GetWindowClass write SetWindowClass;
  58. property WinProc : TVEWMProc read fWinProc write fWinProc;
  59.  
  60. property Title : String read fTitle write SetTitle;
  61. property Settings : PVEDisplaySettings read GetDisplaySettings write SetDisplaySettings;
  62. property Visibled : Boolean read fVisibled write fVisibled;
  63. property Active : Boolean read fActive write fActive;
  64. property Exit : Boolean read fExit write fExit;
  65.  
  66. property KeyState : PKeyState read GetKeyState write SetKeyState;
  67.  
  68. property OnMessage : TVEEvent read fOnMessage write SetOnMessage;
  69. property OnRestore : TVEEvent read fOnRestore write SetOnRestore;
  70. property OnPaint : TVEEvent read fOnPaint write SetOnPaint;
  71. property OnKeyPress : TVEKeyPress read fOnKeyPress write SetOnKeyPress;
  72. property OnResize : TVEEvent read fOnResize write SetOnResize;
  73.  
  74. procedure SetView(dwView: DWORD);
  75.  
  76. end;
  77.  
  78. implementation
  79.  
  80. var
  81. fVEApiWindow : TVEApiWindow;
  82. fVEOldDM : TDeviceMode;
  83.  
  84. procedure SetStandartDisplay;
  85. begin
  86. ChangeDisplaySettings(fVEOldDM,CDS_FULLSCREEN);
  87. end;
  88.  
  89. function SetDisplay : Boolean;
  90. var
  91. dm : DEVMODE;
  92. begin
  93. Result := false;
  94. ZeroMemory(@dm, sizeof(DEVMODE));
  95. dm.dmSize:=sizeof(dm); // Size Of The Devmode Structure
  96. dm.dmPelsWidth := VEDisplaySettings.SCREEN_WIDTH; // Selected Screen Width
  97. dm.dmPelsHeight := VEDisplaySettings.SCREEN_HEIGHT; // Selected Screen Height
  98. dm.dmBitsPerPel := VEDisplaySettings.BPP; // Selected Bits Per Pixel
  99. dm.dmDisplayFrequency := VEDisplaySettings.SCREEN_FREQ;
  100. dm.dmFields:= DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT or DM_DISPLAYFREQUENCY;
  101. if (ChangeDisplaySettings(dm,CDS_FULLSCREEN) <> DISP_CHANGE_SUCCESSFUL) then
  102. begin
  103. VEDisplaySettings.FULLSCREEN := false;
  104. Exit;
  105. end;
  106. Result := true;
  107. end;
  108.  
  109. function WinProcStd(wnd: hwnd; msg: integer; wparam: wparam;
  110. lparam: lparam): lresult; stdcall;
  111. begin
  112. Result := 0;
  113. if Assigned(fVEApiWindow.OnMessage) then fVEApiWindow.OnMessage;
  114. case msg of
  115. WM_ACTIVATE: // Watch For Window Activate Message
  116. begin
  117. if (wParam <> 0) then // Check Minimization State
  118. fVEApiWindow.Active := TRUE // Program Is Active
  119. else
  120. fVEApiWindow.Active := FALSE; // Program Is No Longer Active
  121. exit;
  122. end;
  123. WM_PAINT :
  124. begin
  125. if Assigned(fVEApiWindow.OnPaint) then fVEApiWindow.OnPaint;
  126. end;
  127. WM_CLOSE:
  128. begin
  129. fVEApiWindow.Exit := true;
  130. exit;
  131. end;
  132. WM_DESTROY:
  133. begin
  134. fVEApiWindow.Exit := true;
  135. postquitmessage(0);
  136. exit;
  137. end;
  138. WM_SYSCOMMAND:
  139. begin
  140. case (wParam) of // Check System Calls
  141. SC_SCREENSAVE: begin result := 0; exit; end; // Screensaver Trying To Start?
  142. SC_MONITORPOWER: begin result := 0; exit; end; // Monitor Trying To Enter Powersave?
  143. // Prevent From Happening
  144. end;
  145. if Assigned(fVEApiWindow.OnRestore) then fVEApiWindow.OnRestore;
  146. end;
  147. WM_KEYDOWN:
  148. begin
  149. fVEApiWindow.KeyState[wParam] := true;
  150. if Assigned(fVEApiWindow.OnKeyPress) then fVEApiWindow.OnKeyPress(wParam, true);
  151. exit;
  152. end;
  153. WM_KEYUP:
  154. begin
  155. fVEApiWindow.KeyState[wParam] := false;
  156. if Assigned(fVEApiWindow.OnKeyPress) then fVEApiWindow.OnKeyPress(wParam, false);
  157. exit;
  158. end;
  159. WM_SIZE:
  160. begin
  161. if Assigned(fVEApiWindow.OnResize) then fVEApiWindow.OnResize;
  162. exit;
  163. end;
  164. end;
  165. result := defwindowproc(wnd,msg,wparam,lparam);
  166. end;
  167.  
  168. { TVEApiWindow }
  169.  
  170. constructor TVEApiWindow.Create;
  171. begin
  172. fHandle := 0;
  173. fTitle := \'VEngine API Window\';
  174. fVisibled := false;
  175. fActive := false;
  176. fExit := false;
  177. FillChar(fWindowClass, sizeof(fWindowClass), 0);
  178. FillChar(fKeyState, sizeof(fKeyState), false);
  179. fVEApiWindow := Self;
  180. fOnMessage := nil;
  181. fOnRestore := nil;
  182. fOnPaint := nil;
  183. fOnResize := nil;
  184. EnumDisplaySettings(nil, Cardinal(-1), fVEOldDM);
  185. end;
  186.  
  187. destructor TVEApiWindow.Destroy;
  188. begin
  189. FreeWindow;
  190. inherited;
  191. end;
  192.  
  193. function TVEApiWindow.GetWindowClass: PWndClassex;
  194. begin
  195. Result := @fWindowClass;
  196. end;
  197.  
  198. procedure TVEApiWindow.SetWindowClass(const Value: PWndClassex);
  199. begin
  200. fWindowClass := Value^;
  201. end;
  202.  
  203. function TVEApiWindow.GetWindowMsg: LongBool;
  204. begin
  205. Result := GetMessage(fmmsg,0,0,0);
  206. end;
  207.  
  208. procedure TVEApiWindow.WindowMsgProc;
  209. begin
  210. translatemessage(fmmsg);
  211. dispatchmessage(fmmsg);
  212. end;
  213.  
  214. procedure TVEApiWindow.SetView(dwView : DWORD);
  215. begin
  216. SetWindowLong(fHandle, GWL_STYLE, dwView);
  217. Show;
  218. end;
  219.  
  220. procedure TVEApiWindow.Hide;
  221. begin
  222. ShowWindow(fHandle,SW_HIDE);
  223. fVisibled := false;
  224. end;
  225.  
  226. procedure TVEApiWindow.Show;
  227. begin
  228. ShowWindow(fHandle,SW_SHOW);
  229. SetFocus(fHandle);
  230. Windows.UpdateWindow(fHandle);
  231. fVisibled := true;
  232. end;
  233.  
  234. procedure TVEApiWindow.UpdateWindow;
  235. begin
  236. SetWindowText(fHandle, PChar(fTitle));
  237. if VEDisplaySettings.FULLSCREEN then
  238. begin
  239. SetDisplay;
  240. SetView(WS_POPUPWINDOW or WS_CLIPCHILDREN or WS_CLIPSIBLINGS);
  241. end else
  242. begin
  243. SetStandartDisplay;
  244. SetView(WS_MINIMIZEBOX or WS_SYSMENU or WS_CLIPCHILDREN or WS_CLIPSIBLINGS);
  245. end;
  246.  
  247. SetWindowPos(fHandle, HWND_DESKTOP, 0,0, VEDisplaySettings.SCREEN_WIDTH,VEDisplaySettings.SCREEN_HEIGHT,
  248. SWP_NOZORDER or SWP_NOMOVE);
  249. end;
  250.  
  251. procedure TVEApiWindow.CreateWindow;
  252. var Mode : DWORD;
  253. begin
  254. fWindowClass.cbsize := sizeof (fWindowClass);
  255. fWindowClass.style := cs_hredraw or cs_vredraw;
  256. if Assigned(fWinProc) then
  257. fWindowClass.lpfnwndproc := @fWinProc else
  258. fWindowClass.lpfnwndproc := @WinProcStd;
  259. fWindowClass.cbclsextra := 0;
  260. fWindowClass.cbwndextra := 0;
  261. fWindowClass.hinstance := hinstance;
  262. fWindowClass.hicon := loadicon(0,idi_application);
  263. fWindowClass.hcursor := loadcursor(0,idc_arrow);
  264. fWindowClass.hbrbackground:=COLOR_WINDOW;
  265. fWindowClass.lpszmenuname := nil;
  266. fWindowClass.lpszclassname := \'VEMainWindow\';
  267. registerclassex(fWindowClass);
  268. if VEDisplaySettings.FULLSCREEN then
  269. begin
  270. Mode := WS_POPUPWINDOW;
  271. SetDisplay;
  272. end
  273. else
  274. Mode := WS_SYSMENU or WS_MINIMIZEBOX;
  275.  
  276. fHandle := CreateWindowEx(0,\'VEMainWindow\',PChar(fTitle),
  277. Mode, 0, 0,
  278. VEDisplaySettings.SCREEN_WIDTH,VEDisplaySettings.SCREEN_HEIGHT, 0, 0,fHinstance,nil);
  279. end;
  280.  
  281. procedure TVEApiWindow.FreeWindow;
  282. begin
  283. SetStandartDisplay;
  284. DestroyWindow(fHandle);
  285. fExit := true;
  286. end;
  287.  
  288. procedure TVEApiWindow.SetOnKeyPress(const Value: TVEKeyPress);
  289. begin
  290. fOnKeyPress := Value;
  291. end;
  292.  
  293. procedure TVEApiWindow.SetOnMessage(const Value: TVEEvent);
  294. begin
  295. fOnMessage := Value;
  296. end;
  297.  
  298. procedure TVEApiWindow.SetOnPaint(const Value: TVEEvent);
  299. begin
  300. fOnPaint := Value;
  301. end;
  302.  
  303. procedure TVEApiWindow.SetOnResize(const Value: TVEEvent);
  304. begin
  305. fOnResize := Value;
  306. end;
  307.  
  308. procedure TVEApiWindow.SetOnRestore(const Value: TVEEvent);
  309. begin
  310. fOnRestore := Value;
  311. end;
  312.  
  313. function TVEApiWindow.GetKeyState: PKeyState;
  314. begin
  315. Result := @fKeyState;
  316. end;
  317.  
  318. procedure TVEApiWindow.SetKeyState(const Value: PKeyState);
  319. begin
  320. fKeyState := Value^;
  321. end;
  322.  
  323. function TVEApiWindow.GetDisplaySettings: PVEDisplaySettings;
  324. begin
  325. Result := @VEDisplaySettings;
  326. end;
  327.  
  328. procedure TVEApiWindow.SetDisplaySettings(const Value: PVEDisplaySettings);
  329. begin
  330. VEDisplaySettings := Value^;
  331. end;
  332.  
  333. procedure TVEApiWindow.SetTitle(const Value: String);
  334. begin
  335. fTitle := Value;
  336. SetWindowText(fHandle, PChar(fTitle));
  337. end;
  338.  
  339. function TVEApiWindow.ProcessMessages: Boolean;
  340. begin
  341. if PeekMessage(fmmsg,0,0,0,PM_REMOVE) then
  342. begin
  343. translatemessage(fmmsg);
  344. dispatchmessage(fmmsg);
  345. result := true;
  346. end else
  347. Result := false;
  348. end;
  349.  
  350. procedure TVEApiWindow.ReCreate;
  351. begin
  352. FreeWindow;
  353. CreateWindow;
  354. Show;
  355. fExit := false;
  356. end;
  357.  
  358. end.


Виталий Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: Виталий (статус: 2-ой класс)
Вопрос отправлен: 28 ноября 2008, 19:27
Состояние вопроса: открыт, ответов: 1.

Ответ #1. Отвечает эксперт: Косолапов Дмитрий Юрьевич

Здравствуйте, Виталий!
Такую функцию внутри класса использовать, скорее всего, не получится, так как в Дельфи в этом случае неявно передается указатель на экземпляр класса (Self, грубо говоря). Различать же окна в единой процедуре обработки наверняка можно по переданному HWND.

Ответ отправил: Косолапов Дмитрий Юрьевич (статус: 8-ой класс)
Время отправки: 29 ноября 2008, 10:10


Мини-форум вопроса

Всего сообщений: 3; последнее сообщение — 29 ноября 2008, 14:11; участников в обсуждении: 3.
Мережников Андрей

Мережников Андрей (статус: Абитуриент), 29 ноября 2008, 08:09 [#1]:

можно оставить и одну функцию для всех объектов (хотя,наверное, это не очень правильно). Чтобы не было путаницы необходимо использовать объекты синхронизации (критические секции, семафоры и т.д.)
Вадим К

Вадим К (статус: Академик), 29 ноября 2008, 11:34 [#2]:

To Мережников Андрей
Какие объекты синхронизации? они тут точно не нужны. тут обычного case хватит. нет там что сихнронизировать - вся в одном потоке идет.
Галочка "подтверждения прочтения" - вселенское зло.
Виталий

Виталий (статус: 2-ой класс), 29 ноября 2008, 14:11 [#3]:

добавил текст модуля, скажите что изменить?

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:59
Выполнено за 0.02 сек.