在看《Windows程序设计》,试着用delphi重写里面的例子,第四章最后的例子除了点问题,移动滚动条没有实现想要的结果。代码如下:
program Project1;uses
  Windows,
  Messages,
  SysUtils,
  WinObject,
  Math;const
    AppName ='Windowss';
    NUMLINES = 100;
var
    MyWin:TMyWindow;
    cxChar,cxCaps,cyChar,cxClient,cyClient,iMaxWidth:Integer;function WindowProc(Window:HWND;AMessage:UINT;WParam:WPARAM;
                    LParam:LPARAM):LRESULT;stdcall;export;
var
    dc:HDC;
    tm:TEXTMETRIC;
    ps:TPaintStruct;
    //r:TRect;
    i,x,y,iVertPos,iHorzPos,iPaintBeg,iPaintEnd:Integer;
    si:SCROLLINFO;
begin
    WindowProc:=0;    case AMessage of
        //窗口生成代码
        WM_CREATE:
        begin
            dc:=GetDC(Window);
            GetTextMetrics(dc,tm);
            cxChar := tm.tmAveCharWidth;
            if (tm.tmPitchAndFamily and 1)=1 then
                cxCaps:= Trunc(3 * cxChar / 2)
            else
                cxCaps:= Trunc(2 * cxChar / 2);
            cyChar:=tm.tmHeight+tm.tmExternalLeading;
            ReleaseDC(Window,dc);            iMaxWidth := 40 * cxChar + 22 * cxCaps;
        end;
        //窗口大小改变        WM_SIZE:
        begin
            cxClient:=Loword(LParam);
            cyClient:=HiWord(LParam);    //原来使用错函数了。
            //设置垂直滚动条
            si.cbSize:=SizeOf(si);
            si.fMask:=SIF_RANGE or SIF_PAGE;
            si.nMin:=0;
            si.nMax:=NUMLINES -1;
            si.nPage:=Trunc(cyClient/cyChar);  //问题就出在si.nPage的赋值上
            SetScrollInfo(Window,SB_VERT,si,True);            //设置水平滚动条
            si.cbSize:=SizeOf(si);
            si.fMask:=SIF_RANGE or SIF_PAGE;
            si.nMin:=0;
            si.nMax:=Trunc(2+iMaxWidth/cxChar);   //问题就出在si.nMax的赋值上
            si.nPage:=Trunc(cxClient / cxChar); //问题就出在si.nPage的赋值上
            SetScrollInfo(window,SB_HORZ,si,True);
        end;
        //
        WM_VSCROLL:
        begin
            si.cbSize:=SizeOf(si);
            si.fMask:=SIF_ALL;
            GetScrollInfo(Window,SB_VERT,si);            iVertPos := si.nPos;            case Low(wParam) of
                SB_TOP:
                begin
                  si.nPos:=si.nMin;
                end;
                SB_BOTTOM:
                begin
                  si.nPos:=si.nMax;
                end;
                SB_LINEUP:
                begin
                  si.nPos := si.nPos - 1;
                end;
                SB_LINEDOWN:
                begin
                  si.nPos := si.nPos + 1;
                end;
                SB_PAGEUP:
                begin
                  si.nPos:=si.nPos - si.nPage;
                end;
                SB_PAGEDOWN:
                begin
                  si.nPos:=si.nPos+si.nPage;
                end;
                SB_THUMBTRACK:
                begin
                  si.nPos := si.nTrackPos;
                end;
             end;                si.fMask:=SIF_POS;
                setscrollinfo(window,SB_VERT,si,True);
                GetScrollInfo(window,SB_VERT,si);                if (si.nPos <> iVertPos) then
                begin
                  ScrollWindow(Window,0,cyChar*(iVertPos-si.nPos),nil,nil);    //这里应该用nil还是0?
                  UpdateWindow(Window);
                end;
        end;
        //
        WM_HSCROLL:
        begin
          si.cbSize:=SizeOf(si);
          si.fMask:=SIF_ALL;          GetScrollInfo(Window,SB_HORZ,si);
          iHorzPos:=si.nPos;          case Low(wParam) of
            SB_LINELEFT:
            begin
              si.nPos:= si.nPos - 1;
            end;
            SB_LINERIGHT:
            begin
              si.nPos := si.nPos + 1;
            end;
            SB_PAGELEFT:
            begin
              si.nPos := si.nPos - si.nPage;
            end;
            SB_PAGERIGHT:
            begin
              si.nPos := si.nPos + si.nPage;
            end;
            SB_THUMBPOSITION:
            begin
              si.nPos :=si.nTrackPos;
            end;
          end;          si.fMask:=SIF_POS;
          SetScrollInfo(Window,SB_HORZ,si,True);
          GetScrollInfo(Window,SB_HORZ,si);          if (si.nPos <> iHorzPos) then
          begin
            ScrollWindow(Window,cxChar*(iHorzPos - si.nPos),0,nil,nil);
          end;
        end;
        //重画代码
        WM_PAINT:
        begin
            dc:=BeginPaint(Window,ps);            si.cbSize:=SizeOf(si);
            si.fMask:=SIF_POS;
            GetScrollInfo(Window,SB_VERT,si);
            iVertPos:=si.nPos;            GetScrollInfo(Window,SB_HORZ,si);
            iHorzPos:=si.nPos;            iPaintBeg:= Trunc(Max(0,iVertPos+ps.rcPaint.Top/cyChar));
            iPaintEnd:= Trunc(Min(NUMLINES -1,iVertPos+ps.rcPaint.Bottom / cyChar));            for i:= iPaintBeg to iPaintEnd  do
            begin
                x := cxChar * (1 - iHorzPos);
                y := cyChar * (i - iVertPos);                TextOut(dc,x,y,PChar(IntToStr(i*1000)),Length(IntToStr(i*1000)));
                TextOut(dc,x + 22*cxCaps,y,PChar(IntToStr(i*2000)),Length(IntToStr(i*2000)));
                //SetTextAlign(dc,TA_RIGHT or TA_TOP);
                TextOut(dc,x + 22*cxCaps + 40*cxChar,y,PChar(IntToStr(i*3000)),Length(IntToStr(i*3000)));
            end;
            EndPaint(Window,ps);
        end;
        //窗口关闭代码
        WM_DESTROY:
        begin
            PostQuitMessage(0);
            Exit;
        end;
    end;
    WindowProc:=DefWindowProc(window,AMessage,WParam,LParam);
end;begin
  { TODO -oUser -cConsole Main : Insert code here }
  MyWin:=TMyWindow.Create;
  MyWin.ApplicationName:=AppName;
  MyWin.Caption:='windows程序设计';
  MyWin.Style:=WS_OVERLAPPEDWINDOW or WS_VSCROLL or WS_HSCROLL;
  MyWin.WindowProcedure:= TFNWNDproc(@WindowProc);
  MyWin.WinCreate;
  try
        MyWin.Run;
  finally
        FreeAndNil(MyWin);
  end;
end.
注:TMyWindow在WinObject单元内定义,参考的李维《深入核心VCL架构剖析》第一章关于封装windows窗口的代码,方便自己学习windows sdk时调用。
在delphi2010下编译的程序拖动滚动条后没有任何效果产生——暂时不明白问题所在。
望高手帮忙解答一下。

解决方案 »

  1.   

    找到答案了……被loword函数搞死了……消息判断处用了low函数,正确的应该用loword函数,天哪……
         //
            WM_HSCROLL:
            begin
              si.cbSize:=SizeOf(si);
              si.fMask:=SIF_ALL;          GetScrollInfo(Window,SB_HORZ,si);
              iHorzPos:=si.nPos;          case Low(wParam) of  //这里应该改为Loword(wParam)的。
                SB_LINELEFT:
                begin
                  si.nPos:= si.nPos - 1;
                end;
                SB_LINERIGHT:
                begin
                  si.nPos := si.nPos + 1;
                end;
      

  2.   

    继续看Windows程序设计,后来的看能不能也补上点分。