[fpc-pascal] Win32 API - Scroll Bar inactive
Nico Aragón
na-list at espira.net
Thu Dec 23 16:31:24 CET 2004
El Martes, 9 de Noviembre de 2004 08:08, soumya at tatamotors.com escribiste:
> I am new to Windows programming so please bear with me if it is some
> trivial mistake.
In my humble opinion, the mistake is using plain Windows API :-)
Unless you have a very good reason, it's better to use a higher level library.
To control every aspect of a Winapi GUI program is too much work. I think
that you would find Lazarus libraries, GTK+ bindings and maybe KOL much
easier.
Anyway, I'll try to answer your question.
> I have created a window with :
> hWindow := CreateWindow (AppName,'First Prog',ws_OverlappedWindow or
> WS_VScroll,
> cw_UseDefault,cw_UseDefault,cw_UseDefault,
> cw_UseDefault,0,0,system.MainInstance,Nil);
>
> Now after I write some text on the window with TextOut function that goes
> beyond the window size the window do not scroll.
>
> Please educate me - what is wrong?
It's wrong to think that Windows will take care of scroll. It won't. You need
to:
* Find out how much text fits in a line.
* Draw the text for every physical line.
* Count the resulting lines and the current position so you can answer when
Windows *ask* you how to draw the scroll bar.
By the way, you say that you write the text using TextOut. You should be doing
that inside the code that answers to the WM_PAINT message. Otherwise, the
text will be erased as soon as the window is resized or obscured by another
window.
The following code implements a simple text brower. It doesn't compile because
it depends in a missing file that should provide LoadFile (load a text file
in memory) and GetLine (return the Nth line of the loaded file). But It will
show you how to manage the scroll bar messages.
It's mostly based in Charles Petzold's books and translated by me to Pascal.
If after seeing this, you still think that programming using API is a good
idea, I don't know what would convince you :-)
program GCon03;
{$ifdef fpc}
{$mode delphi}
{$endif}
uses
Windows,
SysUtils,
FileTasks,
// MemStruct,
GCUtils
{$ifdef fpc}
//,FpcCompat
{$else}
,messages
{$endif}
;
var
cxCaps, cxChar, cyChar,
cxClient, cyClient, iMaxWidth: Integer;
{$ifdef fpc}
function ScrollWindow(hWnd:HWND; XAmount:longint; YAmount:longint; Rect:PRECT;
ClipRect:PRECT):WINBOOL; external 'user32' name 'ScrollWindow';
{$else}
{$endif}
function WndProc(Window: HWnd; Message, WParam, LParam: Longint): Longint;
stdcall; export;
var
dc: HDC;
i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd: Integer;
ps: TPaintStruct;
si: TSCROLLINFO;
tm: TTextMetric;
// font: TagLOGFONTA;
Font: TLogFont;
s: string;
rect: TRect;
FileName: string;
begin
case Message of
WM_CREATE:
begin
FileName := 'c:\test.txt';
if not LoadFile(PChar(FileNAme)) then
Halt;
dc := GetDC(Window);
FillChar(font, SizeOf(Font), #0);
Font.lfHeight := FW_NORMAL;
Font.lfCharSet := ANSI_CHARSET;
Font.lfHeight := 18;
Font.lfWidth := 0;
Font.lfPitchAndFamily := FIXED_PITCH;
Font.lfFaceName := 'Courier New';
{$ifdef fpc}
SelectObject(dc, CreateFontIndirect(@Font)) ;
{$else}
SelectObject(dc, CreateFontIndirect(Font)) ;
{$endif}
GetTextMetrics(dc, tm);
cxChar := tm.tmAveCharWidth;
if (tm.tmPitchAndFamily and 1) = 1 then
cxCaps := 3 * cxChar div 2
else
cxCaps := 2 * cxChar div 2;
cyChar := tm.tmHeight + tm.tmExternalLeading ;
// Save the width of the three columns
//iMaxWidth := 40 * cxChar + 22 * cxCaps ;
iMaxWidth := Cardinal(MaxLineLength) * Cardinal(tm.tmAveCharWidth);
DeleteObject (SelectObject (dc, GetStockObject (SYSTEM_FONT))) ;
ReleaseDC(Window, dc) ;
end;
WM_SIZE:
begin
cxClient := LOWORD (lParam) ;
cyClient := HIWORD (lParam) ;
// Set vertical scroll bar range and page size
si.cbSize := SizeOf(si);
si.fMask := SIF_RANGE or SIF_PAGE or SIF_DISABLENOSCROLL ;
si.nMin := 0;
si.nMax := NUMLINES - 1;
si.nPage := cyClient div cyChar;
SetScrollInfo(Window, SB_VERT, si, TRUE) ;
// Set horizontal scroll bar range and page size
si.cbSize := sizeof (si) ;
si.fMask := SIF_RANGE or SIF_PAGE or SIF_DISABLENOSCROLL ;
si.nMin := 0 ;
//si.nMax := 2 + iMaxWidth div cxChar ;
si.nMax := MaxLineLength;
si.nPage := cxClient div cxChar ;
SetScrollInfo (Window, SB_HORZ, si, TRUE) ;
end;
WM_VSCROLL:
begin
// Get all the vertial scroll bar information
si.cbSize := sizeof (si) ;
si.fMask := SIF_ALL ;
GetScrollInfo(Window, SB_VERT, si) ;
// Save the position for comparison later on
iVertPos := si.nPos ;
case LOWORD (wParam) of
SB_TOP: si.nPos := si.nMin ;
SB_BOTTOM: si.nPos := si.nMax ;
SB_LINEUP: Dec(si.nPos);
SB_LINEDOWN: Inc(si.nPos, 1);
SB_PAGEUP: Dec(si.nPos, si.nPage);
SB_PAGEDOWN: Inc(si.nPos, si.nPage);
SB_THUMBTRACK: si.nPos := si.nTrackPos;
end;
// Set the position and then retrieve it. Due to adjustments
// by Windows it may not be the same as the value set.
si.fMask := SIF_POS ;
SetScrollInfo (Window, SB_VERT, si, TRUE) ;
GetScrollInfo (Window, SB_VERT, si) ;
// If the position has changed, scroll the window and update it
if si.nPos <> iVertPos then begin
ScrollWindow (Window, 0, cyChar * (iVertPos - si.nPos), nil, nil) ;
UpdateWindow(Window);
end;
end;
WM_HSCROLL:
begin
// Get all the vertical scroll bar information
si.cbSize := sizeof (si) ;
si.fMask := SIF_ALL ;
// Save the position for comparison later on
GetScrollInfo (Window, SB_HORZ, si) ;
iHorzPos := si.nPos ;
case LOWORD (wParam) of
SB_LINELEFT: Dec(si.nPos);
SB_LINERIGHT: Inc(si.nPos);
SB_PAGELEFT: Dec(si.nPos, si.nPage);
SB_PAGERIGHT: Inc(si.nPos, si.nPage);
SB_THUMBPOSITION: si.nPos := si.nTrackPos;
end;
{ Set the position and then retrieve it. Due to adjustments
by Windows it may not be the same as the value set. }
si.fMask := SIF_POS ;
SetScrollInfo(Window, SB_HORZ, si, TRUE) ;
GetScrollInfo (Window, SB_HORZ, si) ;
{ If the position has changed, scroll the window }
if si.nPos <> iHorzPos then
ScrollWindow(Window, cxChar * (iHorzPos - si.nPos), 0, nil, nil);
end;
wm_EraseBkgnd:
begin
Result := 1;
Exit;
end;
WM_PAINT :
begin
dc := BeginPaint(Window, ps) ;
// Get vertical scroll bar position
si.cbSize := sizeof (si) ;
si.fMask := SIF_POS ;
GetScrollInfo (Window, SB_VERT, si) ;
iVertPos := si.nPos ;
// Get horizontal scroll bar position
GetScrollInfo (Window, SB_HORZ, si) ;
iHorzPos := si.nPos ;
// Find painting limits
iPaintBeg := max(0, iVertPos + ps.rcPaint.top div cyChar) ;
iPaintEnd := min(NUMLINES - 1,
iVertPos + ps.rcPaint.bottom div cyChar) ;
FillChar(font, SizeOf(Font), #0);
Font.lfHeight := FW_NORMAL;
Font.lfCharSet := OEM_CHARSET;
Font.lfHeight := 17;
Font.lfWidth := 0;
Font.lfPitchAndFamily := FIXED_PITCH;
//Font.lfFaceName := 'Courier New';
{$ifdef fpc}
SelectObject(dc, CreateFontIndirect(@Font)) ;
{$else}
SelectObject(dc, CreateFontIndirect(Font)) ;
{$endif}
Rect := ps.rcPaint;
GetClipBox(dc, Rect);
FillRect(dc, Rect, 0);
for i := iPaintBeg {+1} to iPaintEnd do
begin
x := cxChar * (1 - iHorzPos) ;
y := cyChar * (i - iVertPos) ;
s := GetLine(i);
ExtTextOut(dc, x, y, ETO_CLIPPED , @Rect ,PChar(s),Length(s), nil) ;
end;
DeleteObject (SelectObject (dc, GetStockObject (SYSTEM_FONT))) ;
EndPaint (Window, ps) ;
end;
WM_DESTROY: PostQuitMessage(0);
else begin
Result := DefWindowProc (Window, message, wParam, lParam) ;
Exit;
end;
end;
Result := 0;
end;
var
hwnd: THandle;
msg: TagMsg;
wndclass: TWndClass;
ProgramName: string = 'GCon03';
begin
{$ifdef fpc}
wndclass.hInstance := hInstance;
{$else}
wndclass.hInstance := SysInit.hInstance;
{$endif}
with wndclass do begin
style := 0;
lpfnWndProc := @WndProc;
cbClsExtra := 0;
cbWndExtra := 0;
hIcon := LoadIcon(0, IDI_APPLICATION);
hCursor := LoadCursor(0, IDC_ARROW);
hbrBackground := HBRUSH(GetStockObject(WHITE_BRUSH));
lpszMenuName := nil;
lpszClassName := PChar(ProgramName);
if Windows.RegisterClass(wndclass) = 0 then begin
MessageBox(0, 'Program requires Windows NT!', PChar(ProgramName),
MB_ICONERROR);
Halt(0);
end;
hwnd := CreateWindow(PChar(ProgramName), PChar(ProgramName),
WS_OVERLAPPEDWINDOW or WS_VSCROLL or WS_HSCROLL,
LongInt(CW_USEDEFAULT), LongInt(CW_USEDEFAULT),
LongInt(CW_USEDEFAULT), LongInt(CW_USEDEFAULT),
0, 0, hInstance, nil) ;
ShowWindow(hwnd, System.CmdShow) ;
UpdateWindow (hwnd) ;
while GetMessage(msg, 0, 0, 0) do begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
Halt(msg.wParam);
end;
end.
--
saludos,
Nico Aragón
nico at espira.net
http://espira.net/nico/
More information about the fpc-pascal
mailing list