全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1654
推到 Plurk!
推到 Facebook!

視窗縮小再回恢,收不到 WM_PAINT

尚未結案
cancer
高階會員


發表:58
回覆:319
積分:190
註冊:2004-07-31

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-09-07 23:56:00 IP:210.201.xxx.xxx 未訂閱
各位好, 我想自己寫一個文字編輯器,不用 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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-09-08 00:04:22 IP:210.201.xxx.xxx 未訂閱
忘記補充,我如果有問題發問,我都會先使用 Delphi 的 Help, 但可惜的是,Help 裡面的Windows SDK 好像都是一些微軟本身 自己編的資料,並不是 "如何在 Delphi 使用 Windows SDK ", 光是使用哪個 API 要引用個 unit 都沒有講。
william
版主


發表:66
回覆:2535
積分:3048
註冊:2002-07-11

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-09-08 10:26:20 IP:147.8.xxx.xxx 未訂閱
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

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-09-08 22:53:15 IP:210.201.xxx.xxx 未訂閱
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

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-09-09 09:45:02 IP:218.163.xxx.xxx 未訂閱
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

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-09-09 23:27:42 IP:210.201.xxx.xxx 未訂閱
謝謝 Mickey 大大, 一般大家用 Delphi 寫文字編輯器,都用甚麼元件作背景? 另外,Scroll bar 好像也不好搞,我試過加入一個垂直和一個水平的 Scroll bar,Align 屬性前者設為 right,後者設為 bottom, 但這樣的話,視窗右下角會被其中一個 Scroll bar 填滿,這是不對的, 一般編輯器的右下角會留有一個方框,請您現在看一下右下角,兩個 Scroll bar 只有一個角會相接觸,即右下方會空出來。
Mickey
版主


發表:77
回覆:1882
積分:1390
註冊:2002-12-11

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-09-10 09:16:07 IP:218.163.xxx.xxx 未訂閱
修改了一下, 參考看看:
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

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-09-10 22:43:42 IP:210.201.xxx.xxx 未訂閱
TMemo 本身幾乎就是一個文字編輯器了,只待加入功能按鈕而已。 我想直接 TextOut 在 TForm 也可以。
系統時間:2024-05-07 23:50:18
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!