在看《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下编译的程序拖动滚动条后没有任何效果产生——暂时不明白问题所在。
望高手帮忙解答一下。
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下编译的程序拖动滚动条后没有任何效果产生——暂时不明白问题所在。
望高手帮忙解答一下。
//
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;