Link to home
Start Free TrialLog in
Avatar of biroadam
biroadam

asked on

Larger components than 32768 in ScrollBox

I want to view large objects in a ScrollBox (in my particular case only a PaintBox which might be larger than 32768*32768 pixels, but the problem is the same for any kind of VCL components).

I don't know whether is the fault of the Delphi or the Win95, but there is some software bug handling components larger than 32768. To try it, do the following (even design time);
1. Put a ScrollBox, Panel or any kind of component which is able to contain components;
2. Put a PaintBox, Shape, Panel or any other sizeable object in the component above.
3. Set the width of this component to 32000 -- it must work OK;
4. Set the width to 33000 -- the object will disappear or will be displayed in a wrong way.

My questions:
1. Is there a way to correct/avoid this software bug?
2. If not, what ideas do you have for my particular case? (I want on my form a ScrollBox containing a large PaintBox, the OnPaint events will be handled by my application.)
ASKER CERTIFIED SOLUTION
Avatar of kretzschmar
kretzschmar
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
hi igor :-)
Avatar of biroadam
biroadam

ASKER

Hi meikl and Igor!

Thanks for the comment.

meikl:
If it's not a bug, than it's stupidity. 16-bit limitations on a 32-bit OS seems to be quite stupid for me, as well as the fact that the Delphi lets me to use 32-bit values for a 16-bit one.

Igor:
I was thinking on this kind of tricks, but my conclusion is that they won't work.
Your example would work if the scrollbox would allow me to do the repainting after scrolling.
Unfortunately it doesn't.
Let's see an example. I have a 320000*320000 pixel object. Conforming to your idea, I should put a (320000/10=) 32000*32000 pixel PaintBox in the ScrollBox. Then, when I press the scrollbar arrow, I will consider that the image must be scrolled with 80 pixels instead of 8 pixels.
The only but big problem is that the scrollbox has scrolled the image on the screen with 8 pixels already (instead of 80), on the other hand my program has been notified that only an 8 pixel band should be repainted.

Correct me if I'm wrong.


I had another idea: putting a ScrollBox-size PaintBox OVER (and not IN) the ScrollBox, to fit exactly in its client area. So I should use only the scrollbars of the scrollbox, and the actual scrolling should be handled by my program.
My problem is that it is very ugly.

So I'm waiting for some elegant suggestions.

Best regards,
Adam
Hi biroadam,

yes, you are right. You should support scrolling by yourself. Do not put PaintBox over the ScrollBox, create your own control with scrollbars instead. Or place vertical and horizontal scrollbars on form and use it's events to scroll an image.

------
Igor.
Hi Igor!

Of course this was my first idea, but there will be thousands of other problems. Just a few of them:
1. There is no proportional scrollbar in the Delphi's standard components (even if there are free components on the web);
2. With of a vertical and height of a horizontal scrollbar: I will have to use the GetSystemMetrics API function as well as handling the system metrics change messages; dirty and ugly stuff;
3. Wheel mouse events;
4. Repainting problems on resizing: I have no idea how should I repaint these objects avoiding the Delphi's annoying "everyting is repainted hundred times" philosophy.
5. Rewriting the block copy mechanism for scrolling;
6. There are chances to not be compatible with the further versions of Windows (stuffs like smooth scrolling, wheel mouse, which will be handled by further versions of the standard windows scrollboxes, but not by mine);
etc.

So it will be great to use the existing ScrollBox component, but tricking this limitation somehow.

Best regards,
Adam
Hi biroadam,

something strange. I just did an experiment.

1. new application
2. drop scrollbox
3. drop paintbox on scrollbox
4. paintbox.width = 100000, height = 100000
5. paintbox.OnPaint

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
  I: Integer;
begin
  for I := 0 to PaintBox1.Width div 50 do
    PaintBox1.Canvas.TextOut(I*50, 5, IntToStr(I*50));
end;

run project and seems all fine, it scrolled to 100000 without any problems.

-----
Igor
hmm, interesting, which os, igor?
Hi Igor!

I'm too tired to analyse your example, but two things are sure:
1. 'Normal' components such as Shapes can't be larger than 32768 for sure, you can try it at design time;
2. I've tried my bitmap viewer program with a ScrollBox and a PaintBox on Delphi 5 ('couse I thought this problem was a Delphi 4 bug), and the situation was very clear: it worked perfectly for bitmaps smaller than 32768, but the PaintBox disappeared at all for larger bitmaps.

However, I was thinking about your last idea and I decided to build my own scrollbox.
Now it works well, there are only two problems:
1. I don't know how my program/component can realise that the scrollbar width has been changed. I can read the scrollbar width with the GetSystemMetrics function, but I don't know how am I notified when the user modifies the display settings, changing the scrollbar width.
2. When resizing, the repainting works a bit ugly. Do you have any idea how can I prevent the components to be displayed more than once when resizing? I've tried the DisableAlign and EndAlign methods, but no results.

Best regards,
Adam
Watch out, the normal Delphi TScrollBar also has the problem with values greater than 32767...
Hi Adam,

>> 1. I don't know how my program/component can realise that the scrollbar width has been changed.
Should be message WM_WINDOWPOSCHANGED, not sure.

>> 2. When resizing, the repainting works a bit ugly. Do you have any idea how can I prevent the
>> components  to be displayed more than once when resizing?

Every time you need to paint, place custom message into message queue and lock painting mechanism:

// prevent control from painting
LockPaint := true;

// post message to the queue, you will receive this message
// after all current processes was finished
PostMessage(Handle, WM_YOURMESSAGE, .....);

Write WM_YOURMESSAGE handler

var
  M: TMsg;
begin
  while PeekMessage(M, Handle, WM_YOURMESSAGE, WM_YOURMESSAGE, PM_REMOVE) do;
  LockPaint := False;
  // call painting mechanism here
end;

Logic above is usefull to prevent multiply painting while windows process one event. To prevent multiply painting on resizing (few windows events) use additional logic:

Start timer with some dealy value (e.g. 300 ms) on every paint request instead of painting and do paint on WM_TIMER message. Once painting finished you should kill timer.

In additional I can tell you that creating your own scrolling control is really good idea.

----
Igor

Hi Igor!

> Should be message WM_WINDOWPOSCHANGED, not sure.

Quoting the Win32 Programmer's Reference:

"The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place in the Z order has changed as a result of a call to the SetWindowPos function or another window-management function."

So it looks like a completely different thing.
Maybe there isn't a special message for this (but for sure there is one for the system color change), only some generic message which makes the window components to repaint.

>Every time you need to paint, place custom message into
>message queue and lock painting mechanism

It might be a little misunderstanding. I don't want to paint anything, I just want to avoid the Delphi-style multiple component displaying.

Let's see a concrete example:
Form1.Color:=clLime;
put a Panel on the Form1
Panel1.Align:=alClient;

Now, you shouldn't see any Lime color on the screen. However, if you resize the window (even design time), you can see the Lime backgroung under the clBtnFace panel for a few milliseconds (depending on the speed of your PC).

How can you avoid this?

Best regards,
Adam
Hi Adam,

WM_SETTINGCHANGE may be?

Ok, I understood now. You should prevent from painting background and content of parent control while resizing. There is two messages WM_PAINT and WM_ERASEBKGND. You can do the same as described in my comment above but use both message handlers.

-----
Igor.

ADMINISTRATION WILL BE CONTACTING YOU SHORTLY.  Moderators Computer101 or Netminder will return to finalize these if still open in seven days.  Please post closing recommendations before that time.

Question(s) below appears to have been abandoned. Your options are:
 
1. Accept a Comment As Answer (use the button next to the Expert's name).
2. Close the question if the information was not useful to you, but may help others. You must tell the participants why you wish to do this, and allow for Expert response.  This choice will include a refund to you, and will move this question to our PAQ (Previously Asked Question) database.  If you found information outside this question thread, please add it.
3. Ask Community Support to help split points between participating experts, or just comment here with details and we'll respond with the process.
4. Delete the question (if it has no potential value for others).
   --> Post comments for expert of your intention to delete and why
   --> You cannot delete a question with comments, special handling by a Moderator is required.

For special handling needs, please post a zero point question in the link below and include the URL (question QID/link) that it regards with details.
https://www.experts-exchange.com/jsp/qList.jsp?ta=commspt
 
Please click the Help Desk link on the left for Member Guidelines, Member Agreement and the Question/Answer process for further information, if needed.  https://www.experts-exchange.com/jsp/cmtyHelpDesk.jsp

Click you Member Profile to view your question history and keep them all current with updates as the collaboration effort continues, to track all your open and locked questions at this site.  If you are an EE Pro user, use the Power Search option to find them.  Anytime you have questions which are LOCKED with a Proposed Answer but does not serve your needs, please reject it and add comments as to why.  In addition, when you do grade the question, if the grade is less than an A, please add a comment as to why.  This helps all involved, as well as future persons who may access this item in the future to seek help.

To view your open questions, please click the following link(s) and keep them all current with updates.
https://www.experts-exchange.com/questions/Q.20123046.html
https://www.experts-exchange.com/questions/Q.20179315.html
https://www.experts-exchange.com/questions/Q.20264340.html
https://www.experts-exchange.com/questions/Q.20275729.html




PLEASE DO NOT AWARD THE POINTS TO ME.  
 
------------>  EXPERTS:  Please leave any comments regarding your closing recommendations if this item remains inactive another seven (7) days.  Also, if you are interested in the cleanup effort, please click this link https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=commspt&qid=20274643

Moderators will finalize this question if still open in 7 days, by either moving this to the PAQ (Previously Asked Questions) at zero points, deleting it or awarding expert(s) when recommendations are made, or an independent determination can be made.  Expert input is always appreciated to determine the fair outcome.
 
Thank you everyone.
 
Moondancer
Moderator @ Experts Exchange
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

split points between kretzschmar and ITugay

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

Thanks,

geobul
EE Cleanup Volunteer