delphi - No scrollbars appear in an autoscrollable form -
------------------------- original question -------------------------
greetings delphi developers! in delphi 2006 non mdi application, create non-sizeable, autoscrollable, autosizeable form. excerpt form's unit:
uses grid; tgridfrm = class(tform) public grid : tgrid; constructor create(aowner : tcomponent; asize : tpoint); end; implementation constructor tgridfrm.create(aowner: tcomponent; asize : tpoint); begin inherited create(aowner); borderstyle := bssingle; // users not allowed resize form windowstate := wsnormal; borderwidth := 0; autosize := true; autoscroll := true; constraints.maxwidth := screen.width - 1; constraints.maxheight := screen.height - 1; grid := tgrid.create(asize.x, asize.y, self); end;
now, tgrid custom control own canvas of course. excerpt unit:
tgrid = class (tcustomcontrol) public noofcellsx, noofcellsy, cellsize : integer; procedure setzoom(z : integer); constructor create(awidth, aheight : integer; aparent : tform = nil); end; implementation constructor tgrid.create(awidth, aheight : integer; aparent : tform = nil); begin inherited create(aparent); parent := aparent; align := alcustom; left := 0; top := 0; end; procedure tgrid.setzoom(zoom : integer); begin cellsize := zoom * 10 div 100; width := noofcellsx * cellsize; height := noofcellsy * cellsize; end;
in form's unit have arranged things (through applicationevents object) setzoom called zoom value, whenever numeric +/- keys pressed. idea behind have custom control snap upper left corner of form (with predefined margin/borderwidth), , have entire form automatically adjust size whenever zoom in or out of custom control, never extending beyond screen limits. it's working, point scrollbars must become visible: never show up. since autoscrollable form, aren't supposed show whenever control inside form (grid in case) gets larger constrained form , out of way when gets smaller? tried refactoring moving setzoom form's class, no avail. missing here?
----------------- compilable code added afterwards ------------------
the project file:
program myapp; uses forms, grid in 'source\grid.pas', gridform in 'source\gridform.pas' {gridfrm}, main in 'source\main.pas' {mainfrm}; {$r *.res} begin application.initialize; application.createform(tmainfrm, mainfrm); application.run; end.
the main.pas:
unit main; interface uses windows, messages, sysutils, variants, classes, graphics, controls, forms, dialogs, stdctrls; type tmainfrm = class(tform) createnewformbutton: tbutton; procedure formclose(sender: tobject; var action: tcloseaction); procedure createnewformbuttonclick(sender: tobject); end; var mainfrm: tmainfrm; implementation {$r *.dfm} uses gridform; procedure tmainfrm.createnewformbuttonclick(sender: tobject); var aform : tform; begin aform := tgridfrm.create(self, point(15, 15)); aform.show; tgridfrm(aform).grid.setzoom(100); end; procedure tmainfrm.formclose(sender: tobject; var action: tcloseaction); begin action := cafree; end; end.
the gridform.pas:
unit gridform; interface uses windows, messages, sysutils, variants, classes, graphics, controls, forms, dialogs, grid, appevnts; type tgridfrm = class(tform) applicationevents1: tapplicationevents; procedure formclose(sender: tobject; var action: tcloseaction); procedure applicationevents1message(var msg: tagmsg; var handled: boolean); private thegrid : tgrid; public property grid : tgrid read thegrid write thegrid; constructor create(aowner : tcomponent; asize : tpoint); end; var gridfrm: tgridfrm; implementation {$r *.dfm} procedure tgridfrm.applicationevents1message(var msg: tagmsg; var handled: boolean); var keystate : tkeyboardstate; begin if not active begin exit; end; if msg.message = wm_keydown begin getkeyboardstate(keystate); case msg.wparam of vk_add : begin // zoom in grid.setzoom(grid.zoom + 10); handled := true; end; vk_subtract : begin // zoom out grid.setzoom(grid.zoom - 10); handled := true; end; // other keys down here... end; end; end; constructor tgridfrm.create(aowner : tcomponent; asize : tpoint); begin inherited create(aowner); borderstyle := bssingle; borderwidth := 2; autosize := true; autoscroll := true; constraints.maxwidth := screen.width - 1; constraints.maxheight := screen.height - 1; visible := false; grid := tgrid.create(asize.x, asize.y, random(800) + 500, self); end; procedure tgridfrm.formclose(sender: tobject; var action: tcloseaction); begin action := cafree; end; end.
and grid.pas:
unit grid; interface uses stdctrls, sysutils, controls, forms, graphics, dialogs; type tgrid = class (tcustomcontrol) lbl1, lbl2, gridsizeinfolbl, formsizeinfolbl, warninglbl : tlabel; public noofcellsx, noofcellsy, squaresize, // in 1/1000ths of centimeter cellsize, // in pixels zoom : integer; procedure setzoom(z : integer); constructor create(x, y, asquaresize : integer; aparent : tform = nil); end; implementation uses gridform; constructor tgrid.create(x, y, asquaresize : integer; aparent : tform = nil); begin inherited create(aparent); parent := aparent; color := clteal; align := alcustom; left := 0; top := 0; noofcellsx := x; noofcellsy := y; squaresize := asquaresize; lbl1 := tlabel.create(self); lbl2 := tlabel.create(self); gridsizeinfolbl := tlabel.create(self); formsizeinfolbl := tlabel.create(self); warninglbl := tlabel.create(self); lbl1 begin parent := self; caption := 'size of grid: '; width := 55; height := 18; left := 2; top := 1; end; lbl2 begin parent := self; caption := 'size of form: '; width := 75; height := 18; left := 2; top := 19; end; gridsizeinfolbl begin parent := self; width := 100; height := 18; left := 65; top := 1; end; formsizeinfolbl begin parent := self; width := 100; height := 18; left := 65; top := 19; end; warninglbl begin parent := self; width := 150; height := 18; left := 2; top := 39; end; end; procedure tgrid.setzoom(z : integer); begin zoom := z; cellsize := (screen.pixelsperinch * squaresize * zoom) div (1000 * 254); width := noofcellsx * cellsize; height := noofcellsy * cellsize; gridsizeinfolbl.caption := inttostr(width) + 'x' + inttostr(height) + ' (zoom: ' + inttostr(zoom) + ', cellsize zoomed: ' + inttostr(cellsize) + ', squaresize: ' + inttostr(squaresize) + 'mm, squares: ' + inttostr(noofcellsx) + 'x' + inttostr(noofcellsy) + ')'; tgridfrm(parent) begin left := (screen.width - width) div 2; top := (screen.height - height) div 2; formsizeinfolbl.caption := inttostr(width) + 'x' + inttostr(height) + ' (clientarea: ' + inttostr(clientwidth) + 'x' + inttostr(clientheight) + ')'; if self.width > clientwidth if self.height > clientheight warninglbl.caption := 'both scrollbars should appear!' else warninglbl.caption := 'horizontal scrollbar should appear!' else if self.height > clientheight warninglbl.caption := 'vertical scrollbar should appear!' else warninglbl.caption := 'no scrollbars needed'; end; end; end.
code synopsis: click on main form' s button creates autosizeable form, in turn creates child grid of random initial size. numeric +/- keys make grid larger or smaller , form autosized accordingly, no scrollbars ever show up, no matter how large grid becomes (the labels added provide visual feedback).
your problem twofold.
the first is, jerry commented question, autosize
. purpose of autosize resize form such content visible. there can no scrollbars when content visible, 2 properties contradictory.
as such vcl developers have took precaution. below d2007 source:
function tscrollingwincontrol.autoscrollenabled: boolean; begin result := not autosize , not (docksite , usedockmanager); end;
as can see setting autoscroll
has no effect when autosize
set.
you override behavior, virtual method, if wouldn't interfere second fold.
you've decided leave autosize off , calculate , set required size of form depending on workarea size, meet second problem: alignment of grid control.
the below d2007 code when vertical scroll bar wants see if needs adjust:
procedure processvert(control: tcontrol); begin if control.visible case control.align of altop, alnone: if (control.align = altop) or (control.anchors * [aktop, akbottom] = [aktop]) newrange := max(newrange, position + control.top + control.height); albottom: inc(alignmargin, control.height); end; end;
as can see control not have effect on automatic vertical scroll bar if doesn't have either altop
, albottom
or alnone
alignment. yours have alcustom
.
this why overriding autosizing behavior won't help, autosize
depends on controls having "left", "right", "top", "bottom" or "none" aligned controls.
have redesign control taking consideration how vcl internally works. not of internal dependency aspects can documented, have use source kind of enhanced development.
wiki
Comments
Post a Comment