Recent

Author Topic: How to size a csSimple ComboBox at design time.?  (Read 6633 times)

J-23

  • Full Member
  • ***
  • Posts: 108
Re: How to size a csSimple ComboBox at design time.?
« Reply #15 on: May 24, 2020, 03:10:43 pm »
had to add a little to that last one, it seems windows does not properly draw its highlighted box around it, it maybe its in the LCL and I haven't yet found that ?
but in any case, this code will fix that for the time being..
Code: Pascal  [Select][+][-]
  1.  {$IFDEF Windows}
  2.   if (Params.Style and CBS_SIMPLE)<>0 Then
  3.    Begin
  4.     Include(FWinControlFlags, wcfEraseBackground);
  5.     Params.Style:= Params.Style or $400; //CBS_NOINTEGRALHEIGHT
  6.    End
  7.   Else
  8.    Exclude(FWinControlFlags, wcfEraseBackground);
  9.  {$IFEND}                                              
  10.  
Put that in the CustomComBoBox.CreateParams…. in the CustomCombobox.inc file..
place it at the bottom.

 Of course If you want broken down csSimple combo boxes you can keep it as is ;)

Maybe it would be worth adding it to the Tracker bug - then over time it would end up in official sources

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: How to size a csSimple ComboBox at design time.?
« Reply #16 on: May 24, 2020, 04:09:47 pm »
I tried to setup the snv patching system on my PC before but it ended in a total mess on my side.

I did report that code on the bug tracker but they are too busy putting out fires with the snv version.

I've patched the LCL code in several places and made a folder with all the updates and notes so when and if I down load the latest release I check and merge the fixes I have into it.

 Putting out fires tend to be a hard job when there are too many arsonist and not enough fire fighters to go around. ;)
The only true wisdom is knowing you know nothing

wp

  • Hero Member
  • *****
  • Posts: 11853
Re: How to size a csSimple ComboBox at design time.?
« Reply #17 on: May 24, 2020, 07:36:40 pm »
had to add a little to that last one, it seems windows does not properly draw its highlighted box around it, it maybe its in the LCL and I haven't yet found that ?
but in any case, this code will fix that for the time being..
Code: Pascal  [Select][+][-]
  1.  {$IFDEF Windows}
  2.   if (Params.Style and CBS_SIMPLE)<>0 Then
  3.    Begin
  4.     Include(FWinControlFlags, wcfEraseBackground);
  5.     Params.Style:= Params.Style or $400; //CBS_NOINTEGRALHEIGHT
  6.    End
  7.   Else
  8.    Exclude(FWinControlFlags, wcfEraseBackground);
  9.  {$IFEND}                                              
  10.  
Put that in the CustomComBoBox.CreateParams…. in the CustomCombobox.inc file..
place it at the bottom.
I think in order to get this accepted in the bug tracker you must put this code into the win32 widgetset, not in TCustomCombobox.CreateParams. The inventors of the LCL provided the widgetset architecture to keep the outermost units free from lots of IFDEFs like this. The TCombobox is implemented in unit StdCtrls, therefore you should  put your code into Win32WSStdCtrls.pp which resides in folder lcl/interfaces/win32 of your Lazarus installation. There is a class function TWin32WSCustomCombobox.CreateHandle which seems to be suitable for you code (I did not try it integrate it, though). Probably the same modification should be make with the corresponding file for the WinCE widgetset (in folder lcl/interfaces/wince).
« Last Edit: May 24, 2020, 07:44:56 pm by wp »

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: How to size a csSimple ComboBox at design time.?
« Reply #18 on: May 24, 2020, 11:33:41 pm »
had to add a little to that last one, it seems windows does not properly draw its highlighted box around it, it maybe its in the LCL and I haven't yet found that ?
but in any case, this code will fix that for the time being..
Code: Pascal  [Select][+][-]
  1.  {$IFDEF Windows}
  2.   if (Params.Style and CBS_SIMPLE)<>0 Then
  3.    Begin
  4.     Include(FWinControlFlags, wcfEraseBackground);
  5.     Params.Style:= Params.Style or $400; //CBS_NOINTEGRALHEIGHT
  6.    End
  7.   Else
  8.    Exclude(FWinControlFlags, wcfEraseBackground);
  9.  {$IFEND}                                              
  10.  
Put that in the CustomComBoBox.CreateParams…. in the CustomCombobox.inc file..
place it at the bottom.
I think in order to get this accepted in the bug tracker you must put this code into the win32 widgetset, not in TCustomCombobox.CreateParams. The inventors of the LCL provided the widgetset architecture to keep the outermost units free from lots of IFDEFs like this. The TCombobox is implemented in unit StdCtrls, therefore you should  put your code into Win32WSStdCtrls.pp which resides in folder lcl/interfaces/win32 of your Lazarus installation. There is a class function TWin32WSCustomCombobox.CreateHandle which seems to be suitable for you code (I did not try it integrate it, though). Probably the same modification should be make with the corresponding file for the WinCE widgetset (in folder lcl/interfaces/wince).
Ok, I can do that and see what happens...

I think I attempted to do it that way before but it seems no matter what I was doing in that createhandle it appeared to be taking no effect on the final end..
 
 Its like the compile was still linking in the old Object code.

 But I can try again..
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: How to size a csSimple ComboBox at design time.?
« Reply #19 on: May 25, 2020, 12:29:19 am »
@WP
 
 I can't get access to the fWinControlFlags in the Win32WSStdCtrls in the CreateHandle..

 but I was able to put the CBS_NOINTEGRALHEIGHT settings there.

 I only put a conditional statement here because I wasn't sure what gk2, qt would do with the CBS-
additions to the Style .. However, all other stuff is in the TWinControl which is the same across the board..
 So maybe I can just take the conditional compile out.

Code: Pascal  [Select][+][-]
  1.   end;
  2.   // create window
  3.  
  4.   If (CBS_SIMPLE and Params.flags)<>0 Then   { <<<< Added jp}
  5.    Params.Flags := Params.Flags or CBS_NOINTEGRALHEIGHT; {<<<< Added}
  6.  
  7.   FinishCreateWindow(AWinControl, Params, False, True);
  8.   Info.cbSize := SizeOf(Info);
  9.   Win32Extra.GetComboBoxInfo(Params.Window, @Info);                
  10.  

I can not get access to the FwincontrolFlags in there.
have any ideas ?
« Last Edit: May 25, 2020, 12:33:42 am by jamie »
The only true wisdom is knowing you know nothing

wp

  • Hero Member
  • *****
  • Posts: 11853
Re: How to size a csSimple ComboBox at design time.?
« Reply #20 on: May 25, 2020, 01:10:46 am »
Hmm... FWinControlFlags is protected in TWinControl. The WinControl affected is passed as a parameter to CreateHandle. Can you try the usual (ugly) type-cast hack?

Code: Pascal  [Select][+][-]
  1. type
  2.   TWinControlAccess = class(TWinControl);
  3. ...
  4.   Include(TWinControlAccess(AWinControl).FWinControlFlags, wcfEraseBackground);

The other widgetsets will not see any modification here.

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: How to size a csSimple ComboBox at design time.?
« Reply #21 on: May 25, 2020, 02:38:36 am »
class function TWin32WSCustomComboBox.CreateHandle(const AWinControl: TWinControl;   

Code: Pascal  [Select][+][-]
  1.  end;
  2.   // create window
  3.  
  4.   If (CBS_SIMPLE and Params.flags)<>0 Then   {Added jp csSimple comboboxes don't paint correctly otherwise.}
  5.   begin
  6.    Params.Flags := Params.Flags or CBS_NOINTEGRALHEIGHT;
  7.    Include(TWinControlAccess(AWinControl).FWinControlFlags, wcfEraseBackground);
  8.   end Else
  9.    Exclude(TWinControlAccess(AWinControl).FWinControlFlags, wcfEraseBackground);{Added jp}
  10.  
  11.   FinishCreateWindow(AWinControl, Params, False, True);                                  
  12.  

Done

Apparently there is already a class in there just for that purpose...

its strange you just happen to know about that one ;)

I removed all the added stuff in the CreateParams… its all here now...

now how to submit..

The only true wisdom is knowing you know nothing

wp

  • Hero Member
  • *****
  • Posts: 11853
Re: How to size a csSimple ComboBox at design time.?
« Reply #22 on: May 25, 2020, 11:54:56 am »
I added your code to the TWin32WSCustomCalendar.CreateHandle function of my local installation, and I see that it mostly solves the drawing issue due to the integral lineheight. However, there are issues left:

- When the bottom edge of the combobox is anchored to the bottom edge of the form the height of the combobox changes with the form. However, the bottom border line of the listbox is painted only for specific heights, in particular when the height is reduced. (see screenshot)

- When the height of the combobox is changed in an OnClick event of a button then it is not sufficient to simply apply a value to Combobox1.Height, it is also required to call Combobox1.Invalidate explicitly. Otherwise the listbox will be painted only partly.

- It is still not possible to see the listbox when the combobox height is changed at designtime (even when AutoSize is false).

« Last Edit: May 25, 2020, 12:19:03 pm by wp »

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: How to size a csSimple ComboBox at design time.?
« Reply #23 on: May 25, 2020, 12:42:41 pm »
I have seen the bottom edge issue that you have described but only in my Windows 10 PRO, my Home edition of Windows 10 does not show that missing border line..

 I have also had others test it and it varies depending on the OS they are on, for example Win7 seems to work perfectly.

 When testing the height property values between the OS drawing its own list box verses the window that is created in the LCL as the parent window, there is 1 pixel difference in size. It looks like a rounding mismatch. One rounds up while the other trunks it.

 As for the invalidate issue. I'll see if I can do something about that. That is another one that does not happen on all of my WIn10 PC's 

  As for not being able to size the box initially when selecting the csSimple, I have concluded that is a bug in the IDE OI. Unrelated to this issue..

 If you drop a combobox on the form, set the style := csSimple, you can not size it. Save your project, reload the project and now you can size it..
  its being blocked some how because it is accepted if you reload your project with the property preset.
The only true wisdom is knowing you know nothing

wp

  • Hero Member
  • *****
  • Posts: 11853
Re: How to size a csSimple ComboBox at design time.?
« Reply #24 on: May 25, 2020, 01:55:31 pm »
I have seen the bottom edge issue that you have described but only in my Windows 10 PRO, my Home edition of Windows 10 does not show that missing border line..
Mysterious: I have Win10 Home, too.

If you drop a combobox on the form, set the style := csSimple, you can not size it. Save your project, reload the project and now you can size it..
Yes indeed. However, it does not resize smoothly, but in steps as if some kind of IntegralHeight would still be active.

BTW, there are three checks agains csSimple in win32wsstdctrls.pp. Are they really required? I have the feeling that the csSimple style was implemented with the understanding that the listbox should not appear (as was my initial opinion).

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: How to size a csSimple ComboBox at design time.?
« Reply #25 on: May 25, 2020, 03:29:21 pm »
The designer most likely is causing the steps because its trying to stay with the grid on the form.

and yes I have seen the multiple hits in there blocking the csSimple but I think some of those checks are for the drop down mode.

 Currently the only issue I am seeing is the parent window isn't getting a repaint after changing the size in code land without the Invalidate. This reminds me of the old days where it was common to call invalidate always when changing sizes. but the issue here is it appears to be getting late drawing action because I can move my mouse over it and then it completes the draw.
 
 I am still looking for that ester egg ;)
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: How to size a csSimple ComboBox at design time.?
« Reply #26 on: May 26, 2020, 02:05:40 am »
I've been working at this for a while now and finally came up with something...

You can not send a invalidate during any of the comment events that take place while the control is being sized, setup etc....

 Windows blocks a lot of control messages while doing panting and other jobs but I did comeup with the solution...

 I added a message trap in the Message Handler for WM_SIZE, at that point I then issue a InvalidateRect call which then caches up WM_ERASEBKGND and WM_PAINT messages that come later.
 In this message handler Finction..
Code: Pascal  [Select][+][-]
  1. function ComboBoxWindowProc(Window: HWnd; Msg: UInt; WParam: Windows.WParam;
  2.     LParam: Windows.LParam): LResult; stdcall;                                    
  3.  

Add this..
Code: Pascal  [Select][+][-]
  1.      end;
  2.     WM_SIZE:
  3.        begin
  4.           WindowInfo := GetWin32WindowInfo(Window);
  5.          If TCustomcombobox(WindowInfo^.WinControl).Style = csSimple Then
  6.          InvalidateRect(Window,Nil,true);
  7.        end;                                        
  8.  
  9.  

My other code, the last revision still remains in place, it needs to be there to fix those little items I originally found..
 
 This adding of the Message handler fixes the problem of sizing the box via code... etc..

 Let me know what you need.... please.
The only true wisdom is knowing you know nothing

wp

  • Hero Member
  • *****
  • Posts: 11853
Re: How to size a csSimple ComboBox at design time.?
« Reply #27 on: May 27, 2020, 01:03:29 am »
Yes, this fixes the missing bottom line. What's left, in my opinon, is the missing redraw after height changes by code, and the object inspector issue. I do not believe that this a bug of the OI, but a misplaced "(csDesigning in Component)" somewhere.

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: How to size a csSimple ComboBox at design time.?
« Reply #28 on: May 27, 2020, 01:09:03 pm »
The added message I showed you fixes the redraw when height changed by code..

Did you put that in the message loop?

Also I commented those sections that were testing for the csSimple as you pointed out..
and I made a change to the one of them because while in the designer mode it mess up the designer when trying to drag to a new position, the cursor gets off track for that control..

Code: Pascal  [Select][+][-]
  1. class procedure TWin32WSCustomComboBox.AdaptBounds(const AWinControl: TWinControl;
  2.   var Left, Top, Width, Height: integer; var SuppressMove: boolean);
  3. var
  4.   StringList: TWin32ComboBoxStringList;
  5. begin
  6.   {if TCustomComboBox(AWinControl).Style = csSimple Then Exit;}
  7.   StringList := GetStringList(TCustomComboBox(AWinControl));
  8.   if Assigned(StringList) then
  9.     Height := StringList.ComboHeight;
  10. end;                                    
  11.  
Code: Pascal  [Select][+][-]
  1. class procedure TWin32WSCustomComboBox.GetPreferredSize(
  2.   const AWinControl: TWinControl; var PreferredWidth, PreferredHeight: integer;
  3.   WithThemeSpace: Boolean);
  4. begin
  5.   PreferredHeight := 0;
  6.   if (AWinControl.HandleAllocated)and
  7.   (Not(csDesigning in AWinControl.ComponentState)or(TCustomComboBox(AWinControl).Style <> csSimple)) then
  8.   { ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ADDED}
  9.     PreferredHeight := AWinControl.Height;
  10. end;                                                              
  11.  
Code: Pascal  [Select][+][-]
  1.  
  2. class function TWin32WSCustomComboBox.GetStringList(
  3.   const ACustomComboBox: TCustomComboBox): TWin32ComboBoxStringList;
  4. begin
  5.   Result := nil;
  6.  { if ACustomComboBox.Style <> csSimple then}
  7.     Result := TWin32ComboBoxStringList(GetWin32WindowInfo(ACustomComboBox.Handle)^.List);
  8. end;                                                                                        
  9.  

I found that I had to uncomment those events to make things smoother for one of my PC's where as the other it didn't matter..
Btw, on my Win PRO 10 PC, I still have a 1 pixel calculation error at the base of the box while in Themes mode only. So I think the issue here is in the Themes drawing doing the calculations..
 The only other differences between the two pcs is version numbers of Lazarus..
WinPRO = 2.0.8 where as Home edition PC has 2.0.6 on it.. 64 bit for both.

 I have looked high and low, I can not find any reference in the Widget code or CustomCombo code that is causing the IDE issue..

If you would like I can forward you my copy of this complete widget file if you wish ?

The only true wisdom is knowing you know nothing

wp

  • Hero Member
  • *****
  • Posts: 11853
Re: How to size a csSimple ComboBox at design time.?
« Reply #29 on: May 27, 2020, 01:57:28 pm »
If you would like I can forward you my copy of this complete widget file if you wish ?
Yes please, I just was wanting to ask for it to make sure that I've got everything. Then I'll apply it to trunk. I also assigned your bug report to myself. On which Laz version will the modified file be based?

A tiny annoyance (besides the object inspector) is left: The AutoSize property is not working as I would expect, depending on what AutoSize is supposed to do. Well, when I change the font height and AutoSize is active, the combobox height increases, that's fine. But once it is possible to modify the height of the csSimple box with AutoSize=false it is possible to decrease the height of the control such that it becomes less than the height of the edit box. When I activate AutoSize now I would expect that the height jumps back to the height of the default edit box.

 

TinyPortal © 2005-2018