視窗縮小再回恢,收不到 WM_PAINT |
尚未結案
|
cancer
高階會員 發表:58 回覆:319 積分:190 註冊:2004-07-31 發送簡訊給我 |
各位好,
我想自己寫一個文字編輯器,不用 TRichedit 或 TMemo,因為要是使用它們
的話,就永遠無法學會撰寫文字編輯器,所以我決定以最原始的方法,使
用 Tlabel 的Canvas.Textout 來顯示文字,並須處理所有鍵盤和滑鼠事件,
我寫了一個小小的程式來實驗 TLabel的Canvas.Textout 我就遇到一個無法
解決的問題,程式只有一個TForm 和一個 TLabel,在 Form1 的 onPaint
事件寫上 Label1.Canvas.TextOut(20, 20, 'Hello world');
這樣應該可以確保任何情況下,Label1 上面都會顯示 Hello World,可是
程式執行時卻非如此,會有如下不良情形: ※程式一開始執行時,視窗在螢幕中間,沒顯示 Hello World,
這可以在 Form1 的onActivate 送出 WM_PAINT 而得到解決。
※如果沒有顯示Hello World,只要按<放到最大>按鈕,Hello World 出現。
※然後按<縮到最小>按鈕,再按螢幕下面它的圖示,Hello World 消失。
※把視窗拖往左邊超出螢幕,還是不見 Hello World,再繼續向左邊拖,
還是不見 Hello World ,但此時只要向右邊拖一點點,那怕只是一個pixel
而已,Hello World 馬上出現,証明 Form1 有收到 WM_PAINT。
※如果視窗沒有顯示 Hello World ,則把視窗拖向右邊超出螢幕再往左邊拖,
將會同樣得到上面一樣的結果。
※任何時候沒看到 Hello World ,只要按 <放到最大>按鈕,一定會看到
Hello World。 這裡很明顯的一個問題是:只要視窗被縮小在螢幕最下方而成為圖示後,按
該圖示,Form1 不會收到 WM_PAINT 。 我試過在 Form1 的 OnShow, OnResize 事件中加入
SendMessage(self.Handle, WM_PAINT, 0, 0 );
都沒有辨法解決以上問題,其他的 Form 事件很明顯無關。
我試過用 TImage 來代替 TLabel,以上問題即可解決,但這又產生另一個
問題,就是只要用滑鼠拖曳視窗,TImage 裡面的Hello World都會一直閃爍,
但同樣情形下,TLabel就不會,所以不可能考慮用 TImage 來當文字編輯器
的底版。
請問各位,這個問題該如何解決?
不要告訴我用 TRichEdit.Canvas.TextOut
或是 TMemo.Canvas.TextOut
這豈不等於拿賓士車當手推車來用! 先謝再說
|
cancer
高階會員 發表:58 回覆:319 積分:190 註冊:2004-07-31 發送簡訊給我 |
|
william
版主 發表:66 回覆:2535 積分:3048 註冊:2002-07-11 發送簡訊給我 |
From Delphi help: OnPaint occurs before any controls on the form are painted. So the label redraw itself... and remember to set its AutoSize to False. BTW, I think you should let the label draw itself?? e.g.
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TLabel = class(StdCtrls.TLabel) private procedure WMPaint(var Message: TWMPaint); message WM_PAINT; end; TForm1 = class(TForm) Label1: TLabel; end; var Form1: TForm1; implementation {$R *.dfm} procedure TLabel.WMPaint(var Message: TWMPaint); begin inherited; Canvas.TextOut(20,20,'Hello world'); end; end.Remember to set AutoSize to False... |
cancer
高階會員 發表:58 回覆:319 積分:190 註冊:2004-07-31 發送簡訊給我 |
Thanks for your reply. 我想出一個折衷的辦法,有點奇怪,但有用。
除了 Label 之外,再加入一個無用的 TImage,
在form 的 OnPaint 事件函式中多加一行 TImage 的空白 TextOut 如下: procedure TForm1.FormPaint(Sender: TObject);
begin
Label1.Canvas.TextOut(20, 20, 'Hello world!');
Image1.Canvas.TextOut(20, 20, ''); // 用來誘發 OnPaint
end;
這樣的話,在任何情況下,Label1 一定會顯示 Hello World,
不過,這個多餘的 TImage 不知道要放在 Form 的哪裡,就當裝飾品算了。
|
Mickey
版主 發表:77 回覆:1882 積分:1390 註冊:2002-12-11 發送簡訊給我 |
cancer 你好: TLabel 無 Window Handle ( 非 TWinControl ), 個人覺得並不是好的選擇...
若只是要達到你要的目的, 做一個簡單的 Class, 參考看看:
type TDumClass = class(TWinControl) private { Private declarations } FCanvas : TControlCanvas; public { Public declarations } constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property Canvas : TControlCanvas read FCanvas write FCanvas; end; TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormPaint(Sender: TObject); private { Private declarations } public { Public declarations } Dum : TDumClass; end; var Form1: TForm1; implementation {$R *.dfm} { TDumClass } constructor TDumClass.Create(AOwner: TComponent); begin inherited; FCanvas := TControlCanvas.Create; if AOwner is TControl then FCanvas.Control := TControl(AOwner); end; destructor TDumClass.Destroy; begin FCanvas.Free; inherited; end; procedure TForm1.FormCreate(Sender: TObject); begin Dum := TDumClass.Create(self); end; procedure TForm1.FormPaint(Sender: TObject); begin Dum.Canvas.TextOut(20,20,'Hello World!'); end; |
cancer
高階會員 發表:58 回覆:319 積分:190 註冊:2004-07-31 發送簡訊給我 |
|
Mickey
版主 發表:77 回覆:1882 積分:1390 註冊:2002-12-11 發送簡訊給我 |
修改了一下, 參考看看:
type TDumClass = class(TWinControl) private FCanvas : TControlCanvas; procedure WMPaint(var Message: TWMPaint); message WM_PAINT; protected procedure CreateParams(var Params: TCreateParams); override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property Canvas : TControlCanvas read FCanvas write FCanvas; end; TForm1 = class(TForm) procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} { TDumClass } constructor TDumClass.Create(AOwner: TComponent); begin inherited; Width := 100; Height := 100; FCanvas := TControlCanvas.Create; if AOwner is TWinControl then Parent := TWinControl(Aowner); FCanvas.Control := Self; end; procedure TDumClass.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); Params.Style := Params.Style or WS_HSCROLL or WS_VSCROLL;// Both ScrollBar end; destructor TDumClass.Destroy; begin FCanvas.Free; inherited; end; procedure TDumClass.WMPaint(var Message: TWMPaint); begin inherited; FCanvas.TextOut(0,0,'Hello World!'); end; {TForm1} procedure TForm1.FormCreate(Sender: TObject); begin TDumClass.Create(self); end;我沒有用 Delphi 寫過文字編輯器, 所以也不知用何元件. 不過...如果 TMemo 與你想寫的頗接近, 倒是可以參考 TMemo 的 Source (StdCtrls.pas 中) |
cancer
高階會員 發表:58 回覆:319 積分:190 註冊:2004-07-31 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |