Delphi Complete Fashion Manual Coolbar - Realizing Coolbar New Features Chevron
We found that after IE 5.0, IE has a new feature: When the IE window is reduced, the button on the toolbar cannot be fully displayed, a small button appears on the right side of the toolbar (M $ calls it Chevron, actual This is the new characteristics of Coolbar), and then a drop-down list is displayed, and the hidden button is displayed. This greatly facilitates our use of toolbar.
Then how do we make this characteristic of Delphi's TCOOLBAR control? After I have an overnight consultation information (MSDN), "Solid study" (ah, who throws me eggs ...), finally made it! Good things don't dare to swallow, and share it with you. Let's talk about how to implement it. (The following code is done in Delphi 6)
Step 1: Transform Delphi's TCOOLBAND class
It is recommended to back up the comCtrls.PAS file before doing this step. If you add the RBBS_USECHEVRON this value in a BAND in Coolbar, it will display a drop-down button when the width of this BAN is less than a given value, it will display a drop-down button (Chevron). Below to change the file of COMCTRLS.PAS to implement this feature.
Add two properties (Property) in the Published section of Tcoolband:
// modified by joe huang
Property DealWidth: Integer Read FdealWidth Write SetdealWidth; {Used to tell Band When the width of the BAN is smaller than how much is less than how much is less than how much is less than how much is less than how much is less than how much is less than how much is less than how much is smaller button (Chevron)}
Property Usechevron: Boolean Read Fusechevron Write setusechevron; {Used to determine if the band uses this feature}
// end
The writing methods of the two attributes are as follows:
Procedure Tcoolband.Setusechevron (Const Value: Boolean);
Begin
Fusechevron: = Value;
Coolbar.Updatebands;
END;
Procedure Tcoolband.SetdealWidth (Const Value: Integer);
Begin
FDEALWIDTH: = VALUE;
Coolbar.Updatebands;
END;
Complete to TCOOLBAND, but there is a point to remind, although these two properties are in the Publish section, but they can't see in the design period (I don't know how to do). So we can only access them during run.
Step 2: Transform Delphi TCOOLBAR control
In Comctrs.PAS, find the TCOOLBAR.UPDATEITEM method, first add a constant for this method as follows:
// modified by joe huang
RBBS_USECHEVRON = $ 00000200;
// end
Then find this line in this method (the first time fmask: = place):
Fmas: = rbbim_style or rbbim_colors or rbbim_size or rbbim_background or rbbim_image or rbbim_id;
Add the following code under this line:
// modified by joe huang
IF (getcomctlversion> = comctlversionie5) and Band.usechevron kiln {This function is only after IE5} begin
FStyle: = fStyle or RBBS_USECHEVRON;
IF Band.dealwidth> 0 THEN
Begin
Fmask: = fmask or rbbim_idealsize;
CXIDEAL: = Band.dealwidth;
END;
END;
// end
OK! TCOOLBAR transformation is completed. Generate .dcu file for Comctrls.Pas, method: Copy the comCtrls.pas file to an existing project, add it to this project, compile this project, get it .dcu file, will be .dcu File coverage (note backup) Delphi original, in the Delphi6 / Lib directory.
Step 3: Distinguished in a project.
Open Delphi6, create a new project, put into Coolbar1 on Form1, then add Toolbar1 on Coolbar1, and Coolbar1 will automatically generate a band. Set the AutoSize of Toolbar1 to true, wrapable is false and put your button on it. Set up autosize for Coolbar1 for true, showtext to false (Note: To provide me with a way to locate the band.Text property. There are multiple Bands on Coolbar1. You also You can use your own positioning method.), Setting the text of the band with Toolbar1 is MyToolband. The following starts writing code.
Add a CommCtrl unit after the USES of the Form1 unit; write two custom methods in the Implementation section:
{The total width used to get all the visible buttons on Toolbar1.
Used to assign a value DEALWIDTH that we will add to TCOOLBAND in front of us.
That is, the drop-down button is displayed when the width of the BAN is smaller than the total width of all buttons. }
Function GetTBButtonswidth (Atoolbar: Ttoolbar): cardinal
VAR
Arect, ButtonRect: TRECT;
Tbcount, i: integer;
Begin
All: = RECT (0, 0, 0, 0);
TBCount: = atoolbar.perform (tb_buttoncount, 0, 0);
For i: = 0 to TBCount - 1 DO
Begin
AtoolBar.Perform (TB_GETITEMRECT, I, INTEGER (@ButtonRect));
Allt .right: = all.right (ButtonRect.right - ButtonRect.Left);
END;
Result: = ABS (all);
END;
{Used to position Band
Parameters Bandtext gives you what you want to locate the Text property}
Function getCoolband (BandText: String; ACOOLBAR: TCOOLBAR): Integer;
VAR
I: integer;
Begin
RESULT: = -1;
For i: = 0 to acoolbar.bands.count - 1 dobegin
If AcoolBar.Bands.Items [i] .text = BandText Then
Begin
Result: = i;
Break;
END;
END;
END;
Since Coolbar1 can change the position (when there are multiple BANs), we need a variable to store the current location of Toolbar1's Band (later how to capture the location of the Band).
Define a variable in the Private section:
Private CoolBandIndex: Integer;
Add the following code in Form1:
CoolBandIndex: = getCoolband ('MyToolband', Coolbar1); {Location Band Location}
Coolbar1.Bands.Items [CoolBandIndex] .usechevron: = true; {{自己 加 属 属}
Coolbar1.bands.items [CoolbandIndex] .dealWidth: = GetTbButtonswidth (Toolbar1); {{自己 加 属 属}
Now everyone can run the program, then zoom Form1 to cover the top of the Toolbar1, see the drop button (chevron) is not coming! (What? No! Hurry check out if the front step is correct)
Everyone may notice a question: The button on Toolbar1 may be covered, the other half is also displayed outside, can you make a button once partially shade, the entire button does not display? I found that there is a property hideclippedbuttons in the Toolbar in delphi7, just doing this, this property is only played under ME, 2000, XP, but Delphi6 does not have this property. If you are interested, you can refer to Delphi7, it is easy.
Everyone pays attention, the weight is played. How do I click on this drop-down button (Chevron) to display the smuggled button? And how can we notify us when the BAND changes? The answer is the news! When we click on the drop-down button (Chevron), Coolbar sends a RBN_CHEVRONPUSHED message to its parent window; when changing the position of the BAND, the RBN_LAYOUTCHANGED message will be sent. In fact, these two messages are attached to the WM_NOTIFY message. Below we will intercept these two messages in the Form1 window (generally Form1 is the father of Coolbar1, if you put Coolbar1 in other container controls, you should intercept, the same principle is the same in the corresponding window function). Define two variables and a process in the private section:
Private
FclientInstance: TfarProc;
FPREVCLIENTPROC: TFARPROC;
Procedure NewWindowProc (Var Message: TMessage);
Add code in the Form1's onshow event before implementing the NewWindowProc process (this code is written in front of all code in onshow):
Procedure TFORM1.FORMSHOW (Sender: TOBJECT);
Begin
{$ WARNINGS OFF} fclientInstance: = makeObjectInstance (NewWindowProc);
FPREVCLIENTPROC: = Pointer (getwindowl (gwndowl (gwl_wndproc));
Setwindowlong (Form1.Handle, GWL_WndProc, longint (fclientInstance)); {replacing Form1 window function}
{Warnings on}
{...}
END;
Place a PopupMenu1 on Form1, set its alignment as Paright. Used to show the shaded button.
The implementation of the window function NewWindowProc is as follows:
Procedure TFORM1.NEWWINDOWPROC (VAR Message: TMESSAGE);
Type
{Package a TNMRebarchevron structure. This structure is sent with RBN_CHEVRONPUSHED messages. }
Pnmrebarchevron = ^ TNMRebarchevron;
TNMRebarchevron = Record
HDR: TNMHDR;
Uband: uint;
WID: UINT;
Lparam: lparam;
RC: TRECT;
Lparamnm: lparam;
END;
Const
RBN_CHEVRONPUSHED = RBN_FIRST - 10; VAR
ANMHDR: PNMHDR;
ANMREBARCHEVRON: PNMRebarchevron;
ScreenRect: TRECT;
FirstClipButton, i: integer;
Amenuitem: TMenuItem
{This function is used to get the location (index) of the leftmost left in Toolbar1. }
Function GetFirstClipButton (ACOOLBAR: TCOOLBAR; Atoolbar: Ttoolbar): Integer;
VAR
ButtonRect: TRECT;
TBCount, I, TempWidth: Integer;
Begin
RESULT: = -1;
TempWidth: = 0;
TBCount: = atoolbar.perform (tb_buttoncount, 0, 0);
For i: = 0 to TBCount - 1 DO
Begin
AtoolBar.Perform (TB_GETITEMRECT, I, INTEGER (@ButtonRect));
TempWidth: = TempWidth (ButtonRect.right - ButtonRect.Left);
IF Tempwidth> AtoolBar.width Then
Begin
Result: = i;
Break;
END;
END;
END;
Begin
WITH MESSAGE DO
Begin
IF msg = WM_Notify THEN
Begin
ANMHDR: = PNMHDR (LPARAM);
If Anmhdr.code = RBN_CHEVRONPUSHED THEN {We click the drop-down button (Chevron)}
Begin
Anmrebarchevron: = pnmrebarchevron (lparam);
ScreenRect: = Rect (Clienttoscreen (ANMREBARCHEVRON.RC.TOPLEFT), ClientToscreen (ANMREBARCHEVRON.RC.BOTTOTOMRIGHT);
Firstclipbutton: = getFirstClipButton (Coolbar1, Toolbar1); {Get the leftmost of the left side of Toolbar1 on the left side of the left one of the} if firstclipbutton = -1
PopupMenu1.items.clear; {All menuitem} on PopupMenu1
PopupMenu1.Images: = Toolbar1.images;
For i: = firstclipbutton to Toolbar1.buttoncount - 1 DO {Show all covered buttons on popupmenu1 to display a menuitem}
Begin
Amenuitem: = TMenuItem.create (Self);
IF (Toolbar1.Buttons [i] .style = tbsseparator) or (Toolbar1.Buttons [i] .style = TBSDIVIDER) THEN
Amenuitem.caption: = '-'
Else Begin
Amenuitem.caption: = Toolbar1.Buttons [i] .caption;
Amenuitem.ImageIndex: = Toolbar1.Buttons [i] .imageindex;
Amenuitem.enabled: = Toolbar1.buttons [i] .enabled;
Amenuitem.onclick: = Toolbar1.Buttons [i] .onclick;
if Toolbar1.Buttons [i] .Artion <> nil dam
Amenuitem.Action: = Toolbar1.Buttons [i] .act;
END;
PopupMenu1.Items.Add (amenuitem);
END;
PopupMenu1.Popup (ScreenRect.Right 3, ScreenRect.bottom 3);
END ELSE IF ANMHDR.CODE = RBN_LAYOUTCHANGED THEN {Intercept Band Location Change Message}
Begin
For i: = 0 to coolbar1.bands.count - 1 do
Begin
if Coolbar1.Bands.Items [i] .text = 'MyToolband' Then
Begin
CoolBandIndex: = i;
Break;
END;
END;
END;
END;
Result: = CallWindowProc (FPREVCLIENTPROC,
Form1.handle,
MSG,
WPARAM,
lparam;
END;
END;
At this point, the basic code has been completed (running to see the effect, such coolbar is a little Cool look)!
The above code does not fully apply the actual needs, there are two points to pay special attention:
We see the above code is only assigned to DEALWIDTH in the form1.onshow event: coolbar1.bands.Items [CoolBANDEX] .dealwidth: = GetTbButtonswidth (Toolbar1); When we run Toolbar1 by the big button (or Conversely, then DEALWIDTH's value will be inserted with all buttons on Toolbar1, so that the drop-down button (chevron) cannot correctly appear in it. Therefore, as long as the action changes the total width of all buttons of Toolbar1, it is necessary to re-value the DEALWIDTH. When it is displayed on Toolbar1 to display PopupMenu1 to display different states of these buttons, such as a button for a TBSCHECK button, or a TBSDropDown button (with drop-down menu) how to handle it. In the case of these situations, you can see how other famous shared software is implemented, such as ACDSEE5, Winzip, etc. The article is written, and I don't know if I write it. If you have any questions, please come to Email and I discuss, or ask me to Demo. My email: happyjoe@21cn.com