我建了一个
Form1: Tfrom;在其FormPaint事件中写如下代码,但运行根本无显示''Hello, Windows'的字样.
为什么?procedure TForm3.FormPaint(Sender: TObject);
var
  hPaintDC, hClientDC: HDC;
  ps: TPaintStruct;
  hGrayPen, hFillPen, hPrevPen: HPEN;
begin  hPaintDC := BeginPaint(Handle, ps);
  TextOut(hPaintDC, 1, 1, 'Hello, Windows!', 15);  EndPaint(Handle, ps);
end;

解决方案 »

  1.   

    BeginPaint是在接收到WM_PAINT消息时使用的。例如在ApplicationEvents的OnMessage事件里用:
    procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
      var Handled: Boolean);
    var ps: TPaintStruct;
        hPaintDC: HDC;
    begin
      if Msg.message=WM_PAINT then
        begin
          hPaintDC := BeginPaint(Handle, ps);
          TextOut(hPaintDC, 1, 1, 'Hello, Windows!', 15);
          EndPaint(Handle, ps);
        end;
    end;如果要在Form的OnPaint事件里,可以:procedure TForm1.FormPaint(Sender: TObject);
    begin
      TextOut(GetDC(Handle), 1, 1, 'Hello, Windows!', 15);
    end;
    搜索到一段,参考一下:在Window上主要有三种方法得到Client Area的一个HDC句柄。
    1.在WM_PAINT消息中调用 BeginPaint()方法,BeginPaint方法返回一个当前无效区域的HDC句柄,并把该无效区域设置为有效区域。所谓无效区域就是需要应用程序重新绘制的区域,反之则为有效区域。BeginPaint被调用时同时返回了一个PAINTSTRUCT结构,其中给出了本次重绘的Clip Rectangle,所有在这个rectangle之外的绘制操作都不会显示。值得注意的是Petzold在砖头里面反复强调在WM_PAINT消息处理函数中BeginPaint方法需要和EndPaint方法配对使用,还有BeginPaint中返回的HDC不能缓存起来使用。
    2.调用GetDC(hwnd)/ReleaseDC()来获取释放对应Client Rectangle的HDC句柄, 这个句柄没有什么预定义的Clip rectangle, 整个Client Rectangle都可以绘制。但是GetDC()得到的句柄也同样不能缓存起来,也就是说GetDC和ReleaseDC函数要在一个消息处理函数中配对出现。
    一个类似的API是GetWindowDC(),它用于获取整个Window的DC,(client area + non-client area)
    和GetDC一样必须在一次WndProc执行中释放掉,不能缓存。3.调用CreateDC方法还没看到,以后再写。
      

  2.   

    非常感谢,
    已经非常明白,
    但有个问题,为什么FORM运行后不会立即显示出来,要我放大一下FORM窗体,字才显示出来.
      

  3.   

    “放大一下Form窗体”是指最大化?如果是那样的化会触发OnPaint事件,重新将文字显示出来。之前为什么没有显示,不知道你是怎么回事,我这里不会这样。
      

  4.   

    你在From的Create事件里写
    Self.Invalidate;
    或发个信息让窗体重画一次。。
      

  5.   

    如下写的话,FORM仅显示一部分??procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
      var Handled: Boolean);
    var ps: TPaintStruct;
        hPaintDC: HDC;
    begin
      if Msg.message=WM_PAINT then
        begin
          hPaintDC := BeginPaint(Handle, ps);
          TextOut(hPaintDC, 1, 1, 'Hello, Windows!', 15);
          EndPaint(Handle, ps);
        end;
    end;
      

  6.   

    我找到为什么要放在才显示了.
    因为我设置了
    DoubleBuffered := True;
    不过,不明白,这有关系吗?
      

  7.   

    FORM仅显示一部分也是因为我设置了DoubleBuffered := True;不过,不太明白.
      

  8.   

    可能这跟双缓冲有关系。看看Control.pas中procedure TWinControl.WMPaint(var Message: TWMPaint);那一段代码,对FDoubleBuffered的值是分开处理的。
      

  9.   

    是的,我看过.
    如果我用DoubleBuffered := True;那如何不用"最大化Form窗体"就要以显示,我试过Invalidate不管用.这次感谢.