-
При написании невизуального компонента столкнулся с проблемой перехвата сообщений , вот код, в чем ошибка:
unit Proba;
interface
uses
Classes, Controls, Graphics, Windows,Forms, Messages;
type
TWinControl1 = class(TWinControl)
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
TA=Class(TComponent)
private
procedure WMNCMOUSEMOVE(var Message: TMessage);message WM_NCMOUSEMOVE;
protected
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
end;
procedure Register;
implementation
procedure Register;
begin
RegisterClasses([TWinControl1]);
RegisterComponents('Standard', [TA]);
end;
constructor TWinControl1.Create(AOwner: TComponent);
begin
inherited Create(Aowner);
end;
destructor TWinControl1.Destroy;
begin
inherited Destroy;
end;
constructor TA.Create(AOwner: TComponent);
begin
inherited Create(Aowner);
end;
destructor TA.Destroy;
begin
inherited Destroy;
end;
procedure TA.WMNCMOUSEMOVE(var Message: TMessage);
var
s : string;
begin
case Message.wParam of
HTERROR:
s:= 'HTERROR';
HTTRANSPARENT:
s:= 'HTTRANSPARENT';
HTNOWHERE:
s:= 'HTNOWHERE';
HTCLIENT:
s:= 'HTCLIENT';
HTCAPTION:
s:= 'HTCAPTION';
HTSYSMENU:
s:= 'HTSYSMENU';
HTSIZE:
s:= 'HTSIZE';
HTMENU:
s:= 'HTMENU';
HTHSCROLL:
s:= 'HTHSCROLL';
HTVSCROLL:
s:= 'HTVSCROLL';
HTMINBUTTON:
s:= 'HTMINBUTTON';
HTMAXBUTTON:
s:= 'HTMAXBUTTON';
HTLEFT:
s:= 'HTLEFT';
HTRIGHT:
s:= 'HTRIGHT';
HTTOP:
s := 'HTTOP';
HTTOPLEFT:
s:= 'HTTOPLEFT';
HTTOPRIGHT:
s:= 'HTTOPRIGHT';
HTBOTTOM:
s:= 'HTBOTTOM';
HTBOTTOMLEFT:
s:= 'HTBOTTOMLEFT';
HTBOTTOMRIGHT:
s:= 'HTBOTTOMRIGHT';
HTBORDER:
s:= 'HTBORDER';
HTOBJECT:
s:= 'HTOBJECT';
HTCLOSE:
s:= 'HTCLOSE';
HTHELP:
s:= 'HTHELP';
else s:= '';
end;
TForm(Owner).Caption := s;
Message.Result := 0;
end;
end.
При компиляции ошибок нет,после помещения компонента на форму и запуска ни чего не происходит, как не води мышкой. Вручнуб можно запустить, а автоматом не хочет. Подскажите в чем проблема?
-
А что вообще должно происходить ?
-
TForm(Owner).Caption := s; т.е. в загогловке окна пишет где находится курсор.
-
Наверное вы хотели так
type
TA=Class(TComponent)
private
fOldWndProc: TWndMethod;
Form: TCustomForm;
procedure WndProc(var Message: TMessage);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy;override;
end;
implementation
constructor TA.Create(AOwner: TComponent);
var F: TCustomForm;
begin
inherited Create(AOwner);
while (AOwner.Owner <> nil) and not (AOwner is TCustomForm) do AOwner := AOwner.Owner;
if AOwner is TCustomForm then begin
Form := TCustomForm(AOwner);
fOldWndProc := Form.WindowProc;
Form.WindowProc := WndProc;
end;
end;
destructor TA.Destroy;
begin
if Assigned(fOldWndProc) then Form.WindowProc := fOldWndProc;
inherited Destroy;
end;
var f: boolean;
procedure TA.WndProc(var Message: TMessage);
var s : string;
begin
if Assigned(fOldWndProc) then fOldWndProc(Message);
if f then Exit;
F := true;
case Message.wParam of
HTERROR: s:= 'HTERROR';
HTTRANSPARENT: s:= 'HTTRANSPARENT';
else s:= '';
end;
TForm(Owner).Caption := s + inttostr(Random(1000));
f := false;
end;
-
DimaBr интересная мысль: 1) Зачем var f: boolean; 2) Зачем inttostr(Random(1000));
и последнее после компиляции и помещение компонента на форму, редактор Delphi закрывается без предупреждения. В чем проблема не пойму , у меня Delphi 2009
-
1. затем чтобы отсечь сообщения о смене текста в окне, иначе полное зацикливание 2. Прежде чем инсталировать проверьте создавая динамически
-
Что бы отсеять лишние сообщения можно например написать так
if Assigned(fOldWndProc) then fOldWndProc(Message);
if f then Exit;
if Message.Msg = WM_NCHITTEST then exit;
F := true;
case Message.WParam of
-
Автор, тебе чего надо в итоге ?
-
Вот полный код идеи, хотя она стара как мир, но все же интересно ее осуществить . Компонент длжен менять заголовок формы, т.е. управлять им.
unit newCaption;
interface
uses
Classes, Controls, Graphics, Windows,Variants,Forms,
Messages, ExtCtrls, SysUtils, StdCtrls, Dialogs;
type
TPoz = (P_RIGHT,P_CENTER,P_LEFT);
TnewCaption=Class(TComponent)
private
fOldWndProc: TWndMethod;
Form: TCustomForm;
FColorFond: TColor;
FSizeFont : Integer;
FStyleFont: TFontStyles;
FPozition : TPoz;
FCaption: String;
procedure SetColorFond(Value: TColor);
Procedure SetSelect(const Val:TPoz);
protected
public
procedure WMNCPaint(var Msg: TMessage); message WM_NCPAINT;
procedure WMPaint(var Msg: TWMPaint); message WM_PAINT;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
Property ColorFond: TColor Read FColorFond Write SetColorFond;
Property StyleFont: TFontStyles Read FStyleFont Write FStyleFont;
Property Caption: String Read FCaption Write FCaption;
Property SizeFont : Integer Read FSizeFont Write FSizeFont;
Property Pozition : TPoz Read FPozition Write SetSelect;
end;
var
Selek:DWord;
x,y : Integer;
ACanvas: TCanvas;
LabelHeight, LabelWidth, LabelTop: Integer;
caption_height, border3d_y, button_width, border_thickness: Integer;
CaptionBarRect: TRect;
Msg: TWMNCPaint;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Standard', [TnewCaption]);
end;
constructor TnewCaption.Create(AOwner: TComponent);
begin
inherited Create(Aowner);
while (AOwner.Owner <> nil) and not (AOwner is TCustomForm) do AOwner := AOwner.Owner;
if AOwner is TCustomForm then begin
Form := TCustomForm(AOwner);
fOldWndProc := Form.WindowProc;
Form.WindowProc := WMNCPaint;
end;
FPozition := P_LEFT;
FColorFond:=clred;
FStyleFont:=[fsBold];
FSizeFont := 10;
Selek := DT_LEFT;
FCaption:= Form.Caption;Form.Caption:= '';
end;
destructor TnewCaption.Destroy;
begin
if Assigned(fOldWndProc) then Form.WindowProc := fOldWndProc;
inherited Destroy;
end;
procedure TnewCaption.SetColorFond(Value: TColor);
begin
if FColorFond <> Value then
begin
FColorFond := Value;
end;
end;
procedure TnewCaption.SetSelect(const Val:TPoz);
begin
if Val = P_RIGHT then begin FPozition:= P_RIGHT; Selek:= DT_RIGHT; end;
if Val = P_CENTER then begin FPozition:= P_CENTER; Selek:= DT_CENTER; end;
if Val = P_LEFT then begin FPozition:= P_LEFT; Selek:= DT_LEFT; end;
end;
procedure TnewCaption.WMPaint(var Msg: TWMPaint);
begin
border3d_y := GetSystemMetrics(SM_CYEDGE);
button_width := GetSystemMetrics(SM_CXSIZE);
border_thickness := GetSystemMetrics(SM_CYSIZEFRAME);
caption_height := GetSystemMetrics(SM_CYCAPTION)+10;
LabelWidth := (Owner as TForm).Canvas.TextWidth((Owner as TForm).Caption);
LabelHeight := (Owner as TForm).Canvas.TextHeight((Owner as TForm).Caption);
LabelTop := LabelHeight - (caption_height div 2);
CaptionBarRect.Left := border_thickness + border3d_y + button_width;
CaptionBarRect.Right := (Owner as TForm).Width - (border_thickness + border3d_y)
- (button_width * 4);
CaptionBarRect.Top := border_thickness + border3d_y -10;
CaptionBarRect.Bottom := caption_height;
inherited;
ACanvas := TCanvas.Create;
try
ACanvas.Handle := GetWindowDC((Owner as TForm).Handle);
with ACanvas do
begin
Brush.Color := $00DABFA5; Font.Name := 'Tahoma';
Font.Size := FSizeFont;
Font.Color := FColorFond;
Font.Style := FStyleFont;
DrawText(ACanvas.Handle, PChar(' ' + FCaption), Length(FCaption) + 1,
CaptionBarRect, Selek or DT_SINGLELINE or DT_VCENTER);
end;
finally
ReleaseDC((Owner as TForm).Handle, ACanvas.Handle);
ACanvas.Free;
end;
if (Owner as TForm).WindowState = wsMinimized then begin
(Owner as TForm).Caption:= FCaption;
end else begin (Owner as TForm).Caption:= ''; end;
end;
procedure TnewCaption.WMNCPaint(var Msg: TMessage);
begin
if Assigned(fOldWndProc) then fOldWndProc(Msg);
border3d_y := GetSystemMetrics(SM_CYEDGE);
button_width := GetSystemMetrics(SM_CXSIZE);
border_thickness := GetSystemMetrics(SM_CYSIZEFRAME);
caption_height := GetSystemMetrics(SM_CYCAPTION)+10;
LabelWidth := Form.Canvas.TextWidth(Form.Caption);
LabelHeight := Form.Canvas.TextHeight(Form.Caption);
LabelTop := LabelHeight - (caption_height div 2);
CaptionBarRect.Left := border_thickness + border3d_y + button_width;
CaptionBarRect.Right := Form.Width - (border_thickness + border3d_y)
- (button_width * 4);
CaptionBarRect.Top := border_thickness + border3d_y -10;
CaptionBarRect.Bottom := caption_height;
inherited;
ACanvas := TCanvas.Create;
try
ACanvas.Handle := GetWindowDC(Form.Handle);
with ACanvas do
begin
Brush.Color := $00DABFA5; Font.Name := 'Tahoma';
Font.Size := FSizeFont; Font.Color := FColorFond; Font.Style := FStyleFont;
DrawText(ACanvas.Handle, PChar(' ' + FCaption), Length(FCaption) + 1,
CaptionBarRect, Selek or DT_SINGLELINE or DT_VCENTER);
end;
finally
ReleaseDC(Form.Handle, ACanvas.Handle);
ACanvas.Free;
end;
if Form.WindowState = wsMinimized then begin
Form.Caption:= FCaption;
end else begin Form.Caption:= ''; end;
end;
end.
-
DimaBr !, попробовалвнедрить Ваш совет, получаеться плохо. 1) Выдает постоянно ошибку, или зависает полностью. 2) Раз получилось запустить , но надпись мигает. Мигание меньше если применять следующий вид контроля procedure WMNCPaint(var Msg: TWMPaint); message WM_NCPAINT;
но с if AOwner is TCustomForm then begin
Form := TCustomForm(AOwner);
fOldWndProc := Form.WindowProc;
Form.WindowProc := WMNCPaint;
end;
не работает т.к. WindowProc требует var Msg: TMessageМожет есть другой способ перехвата сообщений , более лояльный к var
-
Удалено модератором
-
Удалено модератором
-
Если вы подробнее опишите что в конесном итоге хотите получить, тогда разговор будет намного короче. А так получается что вы думаете об одном, я а о другом
-
> volod (27.02.09 17:56) [8] > Компонент длжен менять заголовок формы, т.е. управлять им.
Как именно?
> TForm(Owner).Caption := s;
а если я на дата-модуль положу? или вовсе вызову TnewCaption.Create(nil)? Только не говорите, что я сам злобный буратино, в данном случае это не канает, т.к. это компонент, вещь по определению для чайника.
-
> а если я на дата-модуль положу? или вовсе вызову TnewCaption. > Create(nil)?
Это как раз лечится выкидыванием исключения в конструкторе, если не Owner is TCustomForm - IDE нормально реагирует на такие исключения. Проблема в другом: мы кладём на форму первый такой компонент, потом второй, потом первый удаляем - второй перестаёт работать, потому что первый восстановил исходное значение WindowProc. Потом удаляем второй компонент, и всё вообще рушится напрочь, потому что он восстановил значение WindowProc, которое было при его создании, т.е. на метод уже не существующего первого компонента. У меня нет никаких идей, как с этим бороться в общем случае, поэтому стараюсь обходиться без таких перехватов, хотя бывали случаи, когда это было совершенно необходимо.
-
> У меня нет никаких идей, как с этим бороться в общем случае Запретить заброску двух компонентов
-
> DimaBr © (02.03.09 11:04) [15] > Запретить заброску двух компонентов
А если речь идёт не о двух экземплярах одного компонента, а о двух разных компонентах? А если эти два компонента писали разные авторы независимо друг от друга?
-
Тогда, востанавливать не запомненную с стандартную procedure TControl.WndProc(var Message: TMessage);
-
> DimaBr © (02.03.09 11:40) [17]
Это спасёт от передачи управления методу несуществующего объекта, но не спасёт от того, что вышестоящие компоненты потеряют функциональность.
-
> Григорьев Антон © (02.03.09 12:00) [18]
И не только вышестоящие, кстати, но и нижестоящие тоже.
-
зато сохранится основная функциональность. Конечно, расстыковку между компонентами разных производителей не побороть. А вообще - это грязный метод, лезть в чужое нутро. Правильнее было бы, написать наследника формы.
-
-
Казалось бы простенький код, но не работает
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
newCaption1.Shadow := not newCaption1.Shadow
end;
-
при изменении размеров формы, мышка "залипает"
-
Project Project1.exe raised exception class EWrongOwner with message 'Должен быть назначен владелец компонента TLine'.
Что такое TLine ?
-
> Компонент полностью управляет заголовком формы А что кроме отрисовка текста заголовка он делает ?
-
Ну и то, о чём говорилось. При заброске 1 и 2 компонентов и удалении 1 и 2 вываливается AV.
-
А Вы на Delphi 2009 пробовали ? Компонент управляет только заголовком формы. Не судите строго это эксперимент, понятное дело, есть недороботки.
-
-
|