Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2011.09.04;
Скачать: [xml.tar.bz2];

Вниз

Субклассинг контрола   Найти похожие ветки 

 
LightGreen   (2010-02-06 15:12) [0]

Всем привет!
Мне нужно динамически отсубклассить контрол на форме. Я подменяю у него WndProc и делаю там отрисовку. Проблема в том, что в VCL есть код, который напрямую берёт родительский DC и начинает там что-то рисовать. Поэтому изображение заметно дёргается, так будто моя отрисовка идёт поверх стандартной. Есть ли возможность это как-то заблокировать? Хотелось бы обойтись без взлома vtable, но рассмотрю любые варианты :)


 
DVM ©   (2010-02-06 15:44) [1]


> Проблема в том, что в VCL есть код, который напрямую берёт
> родительский DC и начинает там что-то рисовать.

Он что сам по себе берет что ли или как следствие обработки сообщений кодом vcl ?


 
DVM ©   (2010-02-06 15:45) [2]

а вообще показывай как делаешь и где дергается


 
LightGreen   (2010-02-07 01:44) [3]

Ну вот, набросал код, как я это делаю (см. ниже). В этом отрывке оно даже не дёргается, а просто рисует свой чекбокс поверх моей надписи, хотя я зову EndPaint, после которого, вроде бы никакой отрисовки быть не может!


unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TCheckBoxModifier = class
   FCheckBox: TCheckBox;
   FOldWndProc: TWndMethod;
   procedure WndProc(var Message: TMessage);
   procedure Paint;
 public
   constructor Create(C: TCheckBox);
   destructor Destroy; override;
 end;

 TForm1 = class(TForm)
   CheckBox1: TCheckBox;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
 private
   FCheckBoxModifier: TCheckBoxModifier;
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

{ TCheckBoxModifier }

constructor TCheckBoxModifier.Create(C: TCheckBox);
begin
 FCheckBox := C;
 FOldWndProc := C.WindowProc;
 C.WindowProc := WndProc;
end;

destructor TCheckBoxModifier.Destroy;
begin
 FCheckBox.WindowProc := FOldWndProc;
 inherited;
end;

procedure TCheckBoxModifier.Paint;
var
 PS: PAINTSTRUCT;
 R: TRect;
begin
 BeginPaint(FCheckBox.Handle, PS);
 if not IsRectEmpty(PS.rcPaint) then
 begin
   R := FCheckBox.ClientRect;
   if FCheckBox.Checked then
     FillRect(PS.hdc, R, GetStockObject(WHITE_BRUSH))
   else
     FillRect(PS.hdc, R, GetStockObject(LTGRAY_BRUSH));
   SetBkMode(PS.hdc, TRANSPARENT);
   DrawText(PS.hdc, PAnsiChar(FCheckBox.Caption), Length(FCheckBox.Caption),
     R, DT_CENTER or DT_VCENTER);
 end;
 EndPaint(FCheckBox.Handle, PS);
end;

procedure TCheckBoxModifier.WndProc(var Message: TMessage);
begin
 case Message.Msg of
   WM_ERASEBKGND:
     Message.Result := 1; // suppress erase bkgnd
   WM_PAINT:
     Paint; // do custom paint
 else
   FOldWndProc(Message);
 end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 FCheckBoxModifier := TCheckBoxModifier.Create(CheckBox1);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 FCheckBoxModifier.Free;
end;

end.


 
Игорь Шевченко ©   (2010-02-07 02:02) [4]

при кликах Paint не вызывается, что легко проверить отладчиком.


 
Игорь Шевченко ©   (2010-02-07 02:35) [5]

Вот более наглядный пример, показывающий, что при кликах на CheckBox WM_PAINT не генерируется:

unit main;

interface
uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   CheckBox1: TCheckBox;
   Memo1: TMemo;
   Button1: TButton;
   procedure FormCreate(Sender: TObject);
   procedure Button1Click(Sender: TObject);
   procedure CheckBox1Click(Sender: TObject);
 private
   Log: TstringList;
   OldCbProc: Pointer;
   procedure NewCbProc (var Message: TMessage);
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 Memo1.Lines.Assign(Log);
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
 Log.Add("Click");
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 Log := TStringList.Create;
 OldCbProc := Pointer(GetWindowLong(CheckBox1.Handle, GWL_WNDPROC));
 SetWindowLong(CheckBox1.Handle, GWL_WNDPROC, DWORD(MakeObjectInstance(NewCbProc)));
end;

procedure TForm1.NewCbProc(var Message: TMessage);
begin
 case Message.Msg of
 WM_PAINT:
   Log.Add("Paint");
 end;
 Message.Result := CallWindowProc(OldCbProc, CheckBox1.Handle,
   Message.Msg, Message.WParam, Message.LParam);
end;

end.


И, соответственно, протокол:

Paint
Click
Click
Click
Click
Click
Click
Click
Click
Click
Click
Click
Click
Click
Click
Click
Click
Click
Paint


 
DVM ©   (2010-02-07 14:03) [6]


> LightGreen

Т.к. при клике WM_PAINT не шлется, а контрол где то внутри себя обрабатывая клик просто перерисовывает себя, надо после клика надо инициировать обновление контрола, что вызовет твою процедуру рисования в любом случае.


 
LightGreen   (2010-02-07 14:24) [7]

Выходит, что это код comctl32 рисует напрямую на DC, а не код VCL... Теперь ясно, откуда появлялось "дёргание". И примерно понятно, как с этим бороться.
Спасибо!



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2011.09.04;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.47 MB
Время: 0.003 c
15-1305232204
Юрий
2011-05-13 00:30
2011.09.04
С днем рождения ! 13 мая 2011 пятница


15-1305138754
NailMan
2011-05-11 22:32
2011.09.04
Ну наконец то начало что то получаться


15-1305577799
Юрий
2011-05-17 00:29
2011.09.04
С днем рождения ! 17 мая 2011 вторник


1-1265789474
bilov
2010-02-10 11:11
2011.09.04
Приложение к среде Delphi - закладки


1-1265458376
LightGreen
2010-02-06 15:12
2011.09.04
Субклассинг контрола





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский