Witam
Mam pytania co do artykułu:
http://4programmers.net/Delphi/Artykuły/Wywołanie_funkcji_zwrotnych_z_klasy
Jak zrobić klasę w której:
- Tworzę kontrolkę np. ListView.
- Subclassuję ją.
- Zapamiętuję "starą" procedurę obsługi komunikatów.
- W nowej procedurze robię to co muszę i odpalam CallWindowProc kiedy zajdzie potrzeba.
- Nowa procedura musi mieć dostęp do zmiennych i metod z klasy.
Zrobiłem sobie klasę dla głównego okna i wszystko ładnie śmiga.
Problem jest natomiast z klasą dla ListView.
Niby po subclassingu nowa procedura działa, ale jak próbuję się odwołać do jakiejś zmiennej z klasy to się włącza klepsydra, aplikacja coś chwilę pomieli i się wyłącza bez żadnego okna błędu.
Zamieszczam kodzik:
unit CListView;
interface
uses Windows, Messages, CommCtrl;
type
TListView = class
private
FHandle, FParentHandle: HWND;
FListViewOldProc: TFNWndProc;
function ListViewProc(uMsg: UINT; wPar: WPARAM; lPar: LPARAM): LRESULT; stdcall;
public
constructor Create; overload;
function CreateWnd(const hParentWnd: HWND; const iX, iY, iW, iH: Integer): Boolean;
property Handle: HWND read FHandle;
property ParentHandle: HWND read FParentHandle;
end;
implementation
constructor TListView.Create;
begin
FHandle := 0;
FParentHandle := 0;
FLabelEditOldProc := nil;
end;
function TListView.ListViewProc(uMsg: UINT; wPar: WPARAM; lPar: LPARAM): LRESULT; stdcall;
var
hWindow: HWND;
Ret: Integer;
begin
Result := 0;
hWindow := Integer(Self);
Ret := GetWindowLong(hWindow, GWL_USERDATA);
if (Ret <> 0) then Self := TListView(Ret)
else Self := TListView(PCREATESTRUCT(lPar)^.lpCreateParams);
case uMsg of
WM_CREATE:
begin
SetWindowLong(hWindow, GWL_USERDATA, Integer(PCREATESTRUCT(lPar)^.lpCreateParams));
end;
WM_LBUTTONDBLCLK:
begin
MessageBeep(5000); //To śmiga
end;
else Result := CallWindowProc(Self.FListViewOldProc, FHandle, uMsg, wPar, lPar);
end;
end;
function TListView.CreateWnd(const hParentWnd: HWND; const iX, iY, iW, iH: Integer): Boolean;
var
CS: TCreateStruct;
begin
FParentHandle := hParentWnd;
CS.lpCreateParams := Self;
FHandle := CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, nil, WS_CHILD or WS_VISIBLE or LVS_REPORT or LVS_NOCOLUMNHEADER or LVS_SINGLESEL, iX, iY, iW, iH, FParentHandle, 0, hInstance, Self);
if (FHandle <> 0) then
begin
ListView_SetExtendedListViewStyle(FHandle, LVS_EX_CHECKBOXES or LVS_EX_GRIDLINES);
FListViewOldProc := Pointer(SetWindowLong(FHandle, GWL_WNDPROC, Integer(@TListView.ListViewProc)));
SendMessage(FHandle, WM_CREATE, 0, Integer(@CS));
end;
Result := (FHandle <> 0);
end;
EDIT: Poprawiłem kod, działa, ale czy to dobre rozwiązanie?