Конференция "Компоненты" » ППомогиомогите , не могу разобраться с невизуальным компонентом !
 
  • volod (27.02.09 14:01) [0]
    При написании невизуального компонента столкнулся с проблемой перехвата сообщений , вот код, в чем ошибка:

    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
       { Protected declarations }
     public

       constructor Create(AOwner: TComponent); override;
       destructor Destroy; override;
     published
     end;

    procedure Register;

    implementation

    procedure Register;
    begin
     RegisterClasses([TWinControl1]);
     RegisterComponents('Standard', [TA]);
    end;
    //********** constructor and destructor **********************

    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.


    При компиляции ошибок нет,после помещения компонента на форму и запуска ни чего не происходит, как не води мышкой.

    Вручнуб можно запустить, а автоматом не хочет.
    Подскажите в чем проблема?
  • DimaBr © (27.02.09 14:38) [1]
    А что вообще должно происходить ?
  • volod (27.02.09 15:00) [2]
    TForm(Owner).Caption := s;


    т.е. в загогловке окна пишет где находится курсор.
  • DimaBr © (27.02.09 15:00) [3]
    Наверное вы хотели так

    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;

  • volod (27.02.09 15:59) [4]
    DimaBr интересная мысль:
    1) Зачем var f: boolean;
    2) Зачем inttostr(Random(1000));

    и последнее после компиляции и помещение компонента на форму,
    редактор Delphi закрывается без предупреждения.
    В чем проблема не пойму , у меня Delphi 2009
  • DimaBr © (27.02.09 16:20) [5]
    1. затем чтобы отсечь сообщения о смене текста в окне, иначе полное зацикливание
    2. Прежде чем инсталировать проверьте создавая динамически
  • DimaBr © (27.02.09 16:34) [6]
    Что бы отсеять лишние сообщения можно например написать так


     if Assigned(fOldWndProc) then fOldWndProc(Message);
     if f then Exit;
     if Message.Msg = WM_NCHITTEST then exit;
     F := true;
     case Message.WParam of

  • Игорь Шевченко © (27.02.09 17:04) [7]
    Автор, тебе чего надо в итоге ?
  • volod (27.02.09 17:56) [8]
    Вот полный код идеи, хотя она стара как мир, но все же интересно ее осуществить .
    Компонент длжен менять заголовок формы, т.е. управлять им.

    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;

    ////////////////  TnewCaption  //////////////////////////
    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:= '';
    // UpdateWindow((Owner as TForm).Handle);

    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;     //clActiveCaption;        //$00FFD5C7
         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;     //clActiveCaption;
         Font.Name := 'Tahoma';
         Font.Size :=  FSizeFont;                        //GetSystemMetrics(SM_CYMENU)
         Font.Color := FColorFond;//clred;
         Font.Style := FStyleFont;//[fsBold];

        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.

  • volod (27.02.09 21:00) [9]
    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
  • имя (28.02.09 22:33) [10]
    Удалено модератором
  • имя (01.03.09 02:20) [11]
    Удалено модератором
  • DimaBr © (02.03.09 09:33) [12]
    Если вы подробнее опишите что в конесном итоге хотите получить, тогда разговор будет намного короче. А так получается что вы думаете об одном, я а о другом
  • KSergey © (02.03.09 09:49) [13]
    > volod   (27.02.09 17:56) [8]
    > Компонент длжен менять заголовок формы, т.е. управлять им.

    Как именно?

    > TForm(Owner).Caption := s;

    а если я на дата-модуль положу? или вовсе вызову TnewCaption.Create(nil)? Только не говорите, что я сам злобный буратино, в данном случае это не канает, т.к. это компонент, вещь по определению для чайника.
  • Григорьев Антон © (02.03.09 11:01) [14]

    > а если я на дата-модуль положу? или вовсе вызову TnewCaption.
    > Create(nil)?

    Это как раз лечится выкидыванием исключения в конструкторе, если не Owner is TCustomForm - IDE нормально реагирует на такие исключения. Проблема в другом: мы кладём на форму первый такой компонент, потом второй, потом первый удаляем - второй перестаёт работать, потому что первый восстановил исходное значение WindowProc. Потом удаляем второй компонент, и всё вообще рушится напрочь, потому что он восстановил значение WindowProc, которое было при его создании, т.е. на метод уже не существующего первого компонента. У меня нет никаких идей, как с этим бороться в общем случае, поэтому стараюсь обходиться без таких перехватов, хотя бывали случаи, когда это было совершенно необходимо.
  • DimaBr © (02.03.09 11:04) [15]
    > У меня нет никаких идей, как с этим бороться в общем случае
    Запретить заброску двух компонентов
  • Григорьев Антон © (02.03.09 11:27) [16]

    > DimaBr ©   (02.03.09 11:04) [15]
    > Запретить заброску двух компонентов

    А если речь идёт не о двух экземплярах одного компонента, а о двух разных компонентах? А если эти два компонента писали разные авторы независимо друг от друга?
  • DimaBr © (02.03.09 11:40) [17]
    Тогда, востанавливать не запомненную с стандартную
    procedure TControl.WndProc(var Message: TMessage);
  • Григорьев Антон © (02.03.09 12:00) [18]

    > DimaBr ©   (02.03.09 11:40) [17]

    Это спасёт от передачи управления методу несуществующего объекта, но не спасёт от того, что вышестоящие компоненты потеряют функциональность.
  • Григорьев Антон © (02.03.09 12:10) [19]

    > Григорьев Антон ©   (02.03.09 12:00) [18]

    И не только вышестоящие, кстати, но и нижестоящие тоже.
  • DimaBr © (02.03.09 12:21) [20]
    зато сохранится основная функциональность.
    Конечно, расстыковку между компонентами разных производителей не побороть. А вообще - это грязный метод, лезть в чужое нутро. Правильнее было бы, написать наследника формы.
  • volod (03.03.09 15:02) [21]
    У кого Delphi 2009 испытайте
    Компонент полностью управляет заголовком формыю

    http://letitbit.net/download/f3cce4761331/Caption.rar.html
  • DimaBr © (03.03.09 16:09) [22]
    Казалось бы простенький код, но не работает

    procedure TForm1.CheckBox1Click(Sender: TObject);
    begin
     newCaption1.Shadow := not newCaption1.Shadow
    end;

  • DimaBr © (03.03.09 16:11) [23]
    при изменении размеров формы, мышка "залипает"
  • DimaBr © (03.03.09 16:14) [24]
    Project Project1.exe raised exception class EWrongOwner with message 'Должен быть назначен владелец компонента TLine'.



    Что такое TLine ?
  • DimaBr © (03.03.09 16:18) [25]
    > Компонент полностью управляет заголовком формы
    А что кроме отрисовка текста заголовка он делает ?
  • DimaBr © (03.03.09 16:21) [26]
    Ну и то, о чём говорилось. При заброске 1 и 2 компонентов и удалении 1 и 2 вываливается AV.
  • volod (03.03.09 20:51) [27]
    А Вы на Delphi 2009 пробовали ?
    Компонент управляет только заголовком формы.
    Не судите строго это эксперимент, понятное дело, есть недороботки.
  • volod (04.03.09 01:26) [28]
    Перезалил, не много доработал.

    http://letitbit.net/download/f3cce4103274/Caption.rar.html
  • Григорьев Антон © (04.03.09 15:03) [29]

    > DimaBr ©   (03.03.09 16:14) [24]
    > Что такое TLine ?

    Видимо, автор взял за основу пример Line из статьи http://www.delphikingdom.com/asp/viewitem.asp?catalogid=169 - как раз там такое исключение выкидывается :)
 
Конференция "Компоненты" » ППомогиомогите , не могу разобраться с невизуальным компонентом !
Есть новые Нет новых   [134465   +63][b:0][p:0.006]