|
Вопрос # 2 138/ вопрос открыт / |
|
Здравствуйте!
Есть вопрос по winapi и непосредственно по языку delphi. Я написал класс для работы с Winapi окнами, он создаёт, удаляет окно, обрабатывает сообщения. С последним как раз и есть проблема.
При создании окна через CreateWindowEx WindowClass.lpfnwndproc присваеватся адрес функции WinProc (обработчик сообщений). Сейчас я написал эту функцию вне класса, но в этом модуле. Так как нужно создавать не один объект окна, то всё окна будут обращаться к одной функции и будет путанница. Если функцию делать внутри класса, то выдаёт ошибку.
Собственно сам вопрос : Как записать функцию внутри класса и использовать её как обработчик сообщений?
Приложение: Переключить в обычный режим-
-
- unit uVEWindows;
-
- interface
-
- uses
- Windows,
- Classes,
- Messages,
- SysUtils,
- uVETypes,
- uVESettings;
-
- type
- TVEApiWindow = class
- private
- fHandle : HWND;
- fHinstance : Cardinal;
- fWindowClass: TWndClassex;
- fmmsg: tagMsg;
- fKeyState : TKeyState;
- fOnMessage, fOnRestore, fOnPaint, fOnResize, fOnProcces : TVEEvent;
- fOnKeyPress : TVEKeyPress;
- fWinProc : TVEWMProc;
- fTitle : String;
- fVisibled, fActive, fExit : Boolean;
- function GetWindowClass: PWndClassex;
- procedure SetWindowClass(const Value: PWndClassex);
- procedure SetOnKeyPress(const Value: TVEKeyPress);
- procedure SetOnMessage(const Value: TVEEvent);
- procedure SetOnPaint(const Value: TVEEvent);
- procedure SetOnResize(const Value: TVEEvent);
- procedure SetOnRestore(const Value: TVEEvent);
- function GetKeyState: PKeyState;
- procedure SetKeyState(const Value: PKeyState);
- function GetDisplaySettings: PVEDisplaySettings;
- procedure SetDisplaySettings(const Value: PVEDisplaySettings);
- procedure SetTitle(const Value: String);
- public
- constructor Create;
- destructor Destroy; override;
- procedure CreateWindow;
- procedure FreeWindow;
-
- function GetWindowMsg : LongBool;
- procedure WindowMsgProc;
- function ProcessMessages : Boolean;
-
- procedure Show;
- procedure Hide;
-
- procedure UpdateWindow;
- procedure ReCreate;
-
- property Handle : HWND read fHandle;
- property WindowClass : PWndClassex read GetWindowClass write SetWindowClass;
- property WinProc : TVEWMProc read fWinProc write fWinProc;
-
- property Title : String read fTitle write SetTitle;
- property Settings : PVEDisplaySettings read GetDisplaySettings write SetDisplaySettings;
- property Visibled : Boolean read fVisibled write fVisibled;
- property Active : Boolean read fActive write fActive;
- property Exit : Boolean read fExit write fExit;
-
- property KeyState : PKeyState read GetKeyState write SetKeyState;
-
- property OnMessage : TVEEvent read fOnMessage write SetOnMessage;
- property OnRestore : TVEEvent read fOnRestore write SetOnRestore;
- property OnPaint : TVEEvent read fOnPaint write SetOnPaint;
- property OnKeyPress : TVEKeyPress read fOnKeyPress write SetOnKeyPress;
- property OnResize : TVEEvent read fOnResize write SetOnResize;
-
- procedure SetView(dwView: DWORD);
-
- end;
-
- implementation
-
- var
- fVEApiWindow : TVEApiWindow;
- fVEOldDM : TDeviceMode;
-
- procedure SetStandartDisplay;
- begin
- ChangeDisplaySettings(fVEOldDM,CDS_FULLSCREEN);
- end;
-
- function SetDisplay : Boolean;
- var
- dm : DEVMODE;
- begin
- Result := false;
- ZeroMemory(@dm, sizeof(DEVMODE));
- dm.dmSize:=sizeof(dm); // Size Of The Devmode Structure
- dm.dmPelsWidth := VEDisplaySettings.SCREEN_WIDTH; // Selected Screen Width
- dm.dmPelsHeight := VEDisplaySettings.SCREEN_HEIGHT; // Selected Screen Height
- dm.dmBitsPerPel := VEDisplaySettings.BPP; // Selected Bits Per Pixel
- dm.dmDisplayFrequency := VEDisplaySettings.SCREEN_FREQ;
- dm.dmFields:= DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT or DM_DISPLAYFREQUENCY;
- if (ChangeDisplaySettings(dm,CDS_FULLSCREEN) <> DISP_CHANGE_SUCCESSFUL) then
- begin
- VEDisplaySettings.FULLSCREEN := false;
- Exit;
- end;
- Result := true;
- end;
-
- function WinProcStd(wnd: hwnd; msg: integer; wparam: wparam;
- lparam: lparam): lresult; stdcall;
- begin
- Result := 0;
- if Assigned(fVEApiWindow.OnMessage) then fVEApiWindow.OnMessage;
- case msg of
- WM_ACTIVATE: // Watch For Window Activate Message
- begin
- if (wParam <> 0) then // Check Minimization State
- fVEApiWindow.Active := TRUE // Program Is Active
- else
- fVEApiWindow.Active := FALSE; // Program Is No Longer Active
- exit;
- end;
- WM_PAINT :
- begin
- if Assigned(fVEApiWindow.OnPaint) then fVEApiWindow.OnPaint;
- end;
- WM_CLOSE:
- begin
- fVEApiWindow.Exit := true;
- exit;
- end;
- WM_DESTROY:
- begin
- fVEApiWindow.Exit := true;
- postquitmessage(0);
- exit;
- end;
- WM_SYSCOMMAND:
- begin
- case (wParam) of // Check System Calls
- SC_SCREENSAVE: begin result := 0; exit; end; // Screensaver Trying To Start?
- SC_MONITORPOWER: begin result := 0; exit; end; // Monitor Trying To Enter Powersave?
- // Prevent From Happening
- end;
- if Assigned(fVEApiWindow.OnRestore) then fVEApiWindow.OnRestore;
- end;
- WM_KEYDOWN:
- begin
- fVEApiWindow.KeyState[wParam] := true;
- if Assigned(fVEApiWindow.OnKeyPress) then fVEApiWindow.OnKeyPress(wParam, true);
- exit;
- end;
- WM_KEYUP:
- begin
- fVEApiWindow.KeyState[wParam] := false;
- if Assigned(fVEApiWindow.OnKeyPress) then fVEApiWindow.OnKeyPress(wParam, false);
- exit;
- end;
- WM_SIZE:
- begin
- if Assigned(fVEApiWindow.OnResize) then fVEApiWindow.OnResize;
- exit;
- end;
- end;
- result := defwindowproc(wnd,msg,wparam,lparam);
- end;
-
- { TVEApiWindow }
-
- constructor TVEApiWindow.Create;
- begin
- fHandle := 0;
- fTitle := \'VEngine API Window\';
- fVisibled := false;
- fActive := false;
- fExit := false;
- FillChar(fWindowClass, sizeof(fWindowClass), 0);
- FillChar(fKeyState, sizeof(fKeyState), false);
- fVEApiWindow := Self;
- fOnMessage := nil;
- fOnRestore := nil;
- fOnPaint := nil;
- fOnResize := nil;
- EnumDisplaySettings(nil, Cardinal(-1), fVEOldDM);
- end;
-
- destructor TVEApiWindow.Destroy;
- begin
- FreeWindow;
- inherited;
- end;
-
- function TVEApiWindow.GetWindowClass: PWndClassex;
- begin
- Result := @fWindowClass;
- end;
-
- procedure TVEApiWindow.SetWindowClass(const Value: PWndClassex);
- begin
- fWindowClass := Value^;
- end;
-
- function TVEApiWindow.GetWindowMsg: LongBool;
- begin
- Result := GetMessage(fmmsg,0,0,0);
- end;
-
- procedure TVEApiWindow.WindowMsgProc;
- begin
- translatemessage(fmmsg);
- dispatchmessage(fmmsg);
- end;
-
- procedure TVEApiWindow.SetView(dwView : DWORD);
- begin
- SetWindowLong(fHandle, GWL_STYLE, dwView);
- Show;
- end;
-
- procedure TVEApiWindow.Hide;
- begin
- ShowWindow(fHandle,SW_HIDE);
- fVisibled := false;
- end;
-
- procedure TVEApiWindow.Show;
- begin
- ShowWindow(fHandle,SW_SHOW);
- SetFocus(fHandle);
- Windows.UpdateWindow(fHandle);
- fVisibled := true;
- end;
-
- procedure TVEApiWindow.UpdateWindow;
- begin
- SetWindowText(fHandle, PChar(fTitle));
- if VEDisplaySettings.FULLSCREEN then
- begin
- SetDisplay;
- SetView(WS_POPUPWINDOW or WS_CLIPCHILDREN or WS_CLIPSIBLINGS);
- end else
- begin
- SetStandartDisplay;
- SetView(WS_MINIMIZEBOX or WS_SYSMENU or WS_CLIPCHILDREN or WS_CLIPSIBLINGS);
- end;
-
- SetWindowPos(fHandle, HWND_DESKTOP, 0,0,
VEDisplaySettings.SCREEN_WIDTH,VEDisplaySettings.SCREEN_HEIGHT,
- SWP_NOZORDER or SWP_NOMOVE);
- end;
-
- procedure TVEApiWindow.CreateWindow;
- var Mode : DWORD;
- begin
- fWindowClass.cbsize := sizeof (fWindowClass);
- fWindowClass.style := cs_hredraw or cs_vredraw;
- if Assigned(fWinProc) then
- fWindowClass.lpfnwndproc := @fWinProc else
- fWindowClass.lpfnwndproc := @WinProcStd;
- fWindowClass.cbclsextra := 0;
- fWindowClass.cbwndextra := 0;
- fWindowClass.hinstance := hinstance;
- fWindowClass.hicon := loadicon(0,idi_application);
- fWindowClass.hcursor := loadcursor(0,idc_arrow);
- fWindowClass.hbrbackground:=COLOR_WINDOW;
- fWindowClass.lpszmenuname := nil;
- fWindowClass.lpszclassname := \'VEMainWindow\';
- registerclassex(fWindowClass);
- if VEDisplaySettings.FULLSCREEN then
- begin
- Mode := WS_POPUPWINDOW;
- SetDisplay;
- end
- else
- Mode := WS_SYSMENU or WS_MINIMIZEBOX;
-
- fHandle := CreateWindowEx(0,\'VEMainWindow\',PChar(fTitle),
- Mode, 0, 0,
- VEDisplaySettings.SCREEN_WIDTH,VEDisplaySettings.SCREEN_HEIGHT, 0, 0,fHinstance,nil);
- end;
-
- procedure TVEApiWindow.FreeWindow;
- begin
- SetStandartDisplay;
- DestroyWindow(fHandle);
- fExit := true;
- end;
-
- procedure TVEApiWindow.SetOnKeyPress(const Value: TVEKeyPress);
- begin
- fOnKeyPress := Value;
- end;
-
- procedure TVEApiWindow.SetOnMessage(const Value: TVEEvent);
- begin
- fOnMessage := Value;
- end;
-
- procedure TVEApiWindow.SetOnPaint(const Value: TVEEvent);
- begin
- fOnPaint := Value;
- end;
-
- procedure TVEApiWindow.SetOnResize(const Value: TVEEvent);
- begin
- fOnResize := Value;
- end;
-
- procedure TVEApiWindow.SetOnRestore(const Value: TVEEvent);
- begin
- fOnRestore := Value;
- end;
-
- function TVEApiWindow.GetKeyState: PKeyState;
- begin
- Result := @fKeyState;
- end;
-
- procedure TVEApiWindow.SetKeyState(const Value: PKeyState);
- begin
- fKeyState := Value^;
- end;
-
- function TVEApiWindow.GetDisplaySettings: PVEDisplaySettings;
- begin
- Result := @VEDisplaySettings;
- end;
-
- procedure TVEApiWindow.SetDisplaySettings(const Value: PVEDisplaySettings);
- begin
- VEDisplaySettings := Value^;
- end;
-
- procedure TVEApiWindow.SetTitle(const Value: String);
- begin
- fTitle := Value;
- SetWindowText(fHandle, PChar(fTitle));
- end;
-
- function TVEApiWindow.ProcessMessages: Boolean;
- begin
- if PeekMessage(fmmsg,0,0,0,PM_REMOVE) then
- begin
- translatemessage(fmmsg);
- dispatchmessage(fmmsg);
- result := true;
- end else
- Result := false;
- end;
-
- procedure TVEApiWindow.ReCreate;
- begin
- FreeWindow;
- CreateWindow;
- Show;
- fExit := false;
- end;
-
- end.
 |
Вопрос задал: Виталий (статус: 2-ой класс)
Вопрос отправлен: 28 ноября 2008, 19:27
Состояние вопроса: открыт, ответов: 1.
|
Ответ #1. Отвечает эксперт: Косолапов Дмитрий Юрьевич
Здравствуйте, Виталий!
Такую функцию внутри класса использовать, скорее всего, не получится, так как в Дельфи в этом случае неявно передается указатель на экземпляр класса (Self, грубо говоря). Различать же окна в единой процедуре обработки наверняка можно по переданному HWND.
Мини-форум вопроса
Всего сообщений: 3; последнее сообщение — 29 ноября 2008, 14:11; участников в обсуждении: 3.
|
Мережников Андрей (статус: Абитуриент), 29 ноября 2008, 08:09 [#1]:
можно оставить и одну функцию для всех объектов (хотя,наверное, это не очень правильно). Чтобы не было путаницы необходимо использовать объекты синхронизации (критические секции, семафоры и т.д.)
|
|
Вадим К (статус: Академик), 29 ноября 2008, 11:34 [#2]:
To Мережников Андрей
Какие объекты синхронизации? они тут точно не нужны. тут обычного case хватит. нет там что сихнронизировать - вся в одном потоке идет.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Виталий (статус: 2-ой класс), 29 ноября 2008, 14:11 [#3]:
добавил текст модуля, скажите что изменить?
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|