Fixed two bugs in xpmenu.

Source: Internet
Author: User
Tags transparent color

Xpmenu is a well-known dephi third-party interface control. Recently, several bugs have been found and two of them have been corrected.

1,First, when drawing menus and toolbar icons, the white part of the image is used as transparent color, which makes image defects very ugly, as shown in:

View the source code of xpmenu. after drawing the drawicon function, the function calculates the position of the icon, calls the graybitmap, dimbitmap, drawbitmapshadow and other functions to process the image, and sets the transparent of the image to true, check the graybitmap, dimbitmap, and drawbitmapshadow functions and find no code that will cause transparent color calculation errors. Looking back, we finally found the problem in txpmenu. menuedrawitem and txpmenu. toolbardrawbutton. Let's take a look at txpmenu. menuedrawitem:

ProcedureTxpmenu. menuedrawitem (Sender: tobject; acanvas: TCanvas; arect: trect;
Selected: Boolean );
Beign
.....
//-------
IfHasbitmapThen
Begin
B. Width: = fmenuitem. bitmap. width;
B. Height: = fmenuitem. bitmap. height;
// + JT
// B. Canvas. Brush. Color: = ftransparentcolor; // acanvas. Brush. color;
B. Canvas. Brush. Color: = B. Canvas. pixels [0, B. Height-1]; // "Todd Asher" <ashert@yadasystems.com>
B. Canvas. fillrect (rect (0, 0, B. Width, B. Height ));
Fmenuitem. bitmap. Transparent: = true;
Fmenuitem. bitmap. transparentmode: = tmauto;
B. Canvas. Draw (0, 0, fmenuitem. Bitmap );
// + JT
End;

IfHasimglstbitmapThen
Begin
{$ Ifdef ver5u}
IfFmenuitem. Parent. submenuimages <>Nil Then
Begin
Imglisthandle: = fmenuitem. Parent. submenuimages. Handle;
Imgindex: = fmenuitem. imageindex;

B. Width: = fmenuitem. Parent. submenuimages. width;
B. Height: = fmenuitem. Parent. submenuimages. height;
// B. Canvas. Brush. Color: = ftransparentcolor; // acanvas. Brush. color; // + JT
B. Canvas. Brush. Color: = B. Canvas. pixels [0, B. Height-1]; // "Todd Asher" <ashert@yadasystems.com>
B. Canvas. fillrect (rect (0, 0, B. Width, B. Height ));
Imagelist_drawex (imglisthandle, imgindex,
B. Canvas. Handle, 0, 0, 0, 0, clnone, clnone, ild_transparent );

End
Else

{$ Endif}
IfFmenuitem. Parent. getparentmenu. Images <>Nil then
Begin
Imglisthandle: = fmenuitem. Parent. getparentmenu. Images. Handle;
Imgindex: = fmenuitem. imageindex;

B. Width: = fmenuitem. Parent. getparentmenu. Images. width;
B. Height: = fmenuitem. Parent. getparentmenu. Images. height;
// B. Canvas. Brush. Color: = ftransparentcolor; // acanvas. pixels [2, 2]; // + JT
B. Canvas. Brush. Color: = B. Canvas. pixels [0, B. Height-1]; // "Todd Asher" <ashert@yadasystems.com>
B. Canvas. fillrect (rect (0, 0, B. Width, B. Height ));
Imagelist_drawex (imglisthandle, imgindex,
B. Canvas. Handle, 0, 0, 0, 0, clnone, clnone, ild_transparent );

 End;

End;
......
If
(B <> nil) and (B. width> 0)Then// X
Drawicon (fmenuitem, acanvas, B, iconrect,
Selected or drawtopmenuborder, false, fmenuitem. enabled, fmenuitem. Checked,
Ftopmenu, fmenu. isrighttoleft );
......
End;

Obviously, except for the author of xpmenu, + JT, Asher, and X have both modified the code. The problem lies in the Code modified by + jk, it uses B (tbitmap) first ). canvas. pixels [0, B. the color at height-1] is filled with B, and then the icon to be displayed is drawn to B. The drawicon will be called to display the Icon later. Unfortunately, the calculation error + JT is incorrect, B (tbitmap) at that time ). canvas. pixels [0, B. the height-1] value is exactly $ ffffff (white). When imagelist_drawex is called with the ild_transparent parameter, the base color (such as pink) of the source image is removed, and the background color of the icons drawn by drawicon is white, at last, all the white parts of the icon are hollowed out. + JT is really a bad thing.
The cause is found, and now you can directly remove the + JT code. The original program becomes:

ProcedureTxpmenu. menuedrawitem (Sender: tobject; acanvas: TCanvas; arect: trect;
Selected: Boolean );
Beign
.....
//-------
IfHasbitmapThen
Begin
B. Width: = fmenuitem. bitmap. width;
B. Height: = fmenuitem. bitmap. height;
{Modify: The transparent color of the icons drawn by conch 2004-12-16 is incorrect.
// + JT
// B. Canvas. Brush. Color: = ftransparentcolor; // acanvas. Brush. color;
B. Canvas. Brush. Color: = B. Canvas. pixels [0, B. Height-1]; // "Todd Asher" <ashert@yadasystems.com>
B. Canvas. fillrect (rect (0, 0, B. Width, B. Height ));
Fmenuitem. bitmap. Transparent: = true;
Fmenuitem. bitmap. transparentmode: = tmauto;
}
B. Canvas. Draw (0, 0, fmenuitem. Bitmap );
// + JT
End;

IfHasimglstbitmapThen
Begin
{$ Ifdef ver5u}
IfFmenuitem. Parent. submenuimages <>Nil Then
Begin
Imglisthandle: = fmenuitem. Parent. submenuimages. Handle;
Imgindex: = fmenuitem. imageindex;

B. Width: = fmenuitem. Parent. submenuimages. width;
B. Height: = fmenuitem. Parent. submenuimages. height;
{Modify: The transparent color of the icons drawn by conch 2004-12-16 is incorrect.
// B. Canvas. Brush. Color: = ftransparentcolor; // acanvas. Brush. color; // + JT
B. Canvas. Brush. Color: = B. Canvas. pixels [0, B. Height-1]; // "Todd Asher" <ashert@yadasystems.com>
B. Canvas. fillrect (rect (0, 0, B. Width, B. Height ));
Imagelist_drawex (imglisthandle, imgindex,
B. Canvas. Handle, 0, 0, 0, 0, clnone, clnone, ild_transparent );
}
Imagelist_drawex (imglisthandle, imgindex,
B. Canvas. Handle, 0, 0, 0, 0, clnone, clnone, ild_normal );
// Conch

End
Else

{$ Endif}
IfFmenuitem. Parent. getparentmenu. Images <>Nil then
Begin
Imglisthandle: = fmenuitem. Parent. getparentmenu. Images. Handle;
Imgindex: = fmenuitem. imageindex;

B. Width: = fmenuitem. Parent. getparentmenu. Images. width;
B. Height: = fmenuitem. Parent. getparentmenu. Images. height;
{Modify: The transparent color of the icons drawn by conch 2004-12-16 is incorrect.
// B. Canvas. Brush. Color: = ftransparentcolor; // acanvas. pixels [2, 2]; // + JT
B. Canvas. Brush. Color: = B. Canvas. pixels [0, B. Height-1]; // "Todd Asher" <ashert@yadasystems.com>
B. Canvas. fillrect (rect (0, 0, B. Width, B. Height ));
Imagelist_drawex (imglisthandle, imgindex,
B. Canvas. Handle, 0, 0, 0, 0, clnone, clnone, ild_transparent );
}
Imagelist_drawex (imglisthandle, imgindex,
B. Canvas. Handle, 0, 0, 0, 0, clnone, clnone, ild_normal );
// Conch

 End;

End;
......
If
(B <> nil) and (B. width> 0)Then// X
Drawicon (fmenuitem, acanvas, B, iconrect,
Selected or drawtopmenuborder, false, fmenuitem. enabled, fmenuitem. Checked,
Ftopmenu, fmenu. isrighttoleft );
......
End;

The same is true for txpmenu. toolbardrawbutton.

ProcedureTxpmenu. toolbardrawbutton (Sender: ttoolbar;
Button: ttoolbutton; State: tcustomdrawstate; var defaultdraw: Boolean );
Begin
IfCandrawThen
Begin {candraw}
{Modify: The transparent color of the icons drawn by conch 2004-12-16 is incorrect.
// B. Canvas. Brush. Color: = transparentcolor; // acanvas. Brush. color; // + JT
B. Canvas. Brush. Color: = B. Canvas. pixels [0, B. Height-1]; // "Todd Asher" <ashert@yadasystems.com>
B. Canvas. fillrect (rect (0, 0, B. Width, B. Height ));
Imagelist_drawex (imglsthand, button. imageindex,
B. Canvas. Handle, 0, 0, 0, 0, clnone, clnone, ild_transparent );
}
Imagelist_drawex (imglsthand, button. imageindex,
B. Canvas. Handle, 0, 0, 0, 0, clnone, clnone, ild_normal );
// Conch
......
End;

2,The second problem is that the shadow of the menu is too dull and it is a fixed gray block (of course, it refers to the system before WINXP ),

The menu shadow is drawn by the txpmenu. drawwindowborder function. Here we can see that the + JT has been modified, but the + JT annotation method is a bit special. We cannot see the original code of the author, which has been modified by the + JT, however, it is certain that + JT has had a lot of hard work. This function removes the 3D border from windows and turns it into a flat officexp style menu. If you want to change the shadow effect by mixing the background pixels like the WINXP menu, you must make a major change to the source code, but use third-party controls to facilitate ease of use, if you do that, it would be too contrary to the original intention. Therefore, I used a compromise to reduce the gray area, which seems to be more pleasing to the eye. The final effect is as follows:

The modified txpmenu. drawwindowborder function is as follows:

ProcedureTxpmenu. drawwindowborder (hwnd: hwnd; isrighttoleft: Boolean );
VaR
Wrect: trect;
Dcanvas: TCanvas;
WDC: HDC; // + JT

Regiontype: integer; // + JT
R1, R2, wR, Region: hrgn; // + JT
Rgnr: trect; // + JT
Begin

If(Hwnd <= 0)Or(Fsetting1_wrng)Then
 Begin
Exit;
 End;
// + JT
WDC: = getwindowdc (hwnd); // getwindowtopwindow
 IfWDC = 0ThenExit;
// + JT
Fsetting1_wrng: = true; // + JT
Dcanvas: = TCanvas. Create;
 Try
Dcanvas. Handle: = WDC; // + JT
Getwindowrect (hwnd, wrect );
// + JT
Wrect. Right: = wrect. Right-WRect.Left;
Wrect. Bottom: = wrect. Bottom-WRect.Top;
Wrect. Top: = 0;
Wrect. Left: = 0;
IfGetwindowlong (hwnd, gwl_wndproc) <> INTEGER (@ menuwindowproc)Then
Begin
Setwindowlong (hwnd, gwl_userdata, getwindowlong (hwnd, gwl_wndproc ));
Setwindowlong (hwnd, gwl_wndproc, INTEGER (@ menuwindowproc ));
End;
{Modify: conch 2004-11-04 the shadow is too ugly.
If not iswxp then
Begin
WR: = createrectrgn (0, 0, 0 );
Regiontype: = getjavaswrgn (hwnd, wr );
Getrgnbox (WR, rgnr );
Deleteobject (WR );
If (regiontype = Error) or (ABS (rgnr. Right-WRect.Right)> 5) or (ABS (rgnr. Bottom-WRect.Bottom)> 5) then
Begin
Region: = createrectrgn (0, 0, 0 );
R1: = createrectrgn (wrect. Left, wrect. Top, wrect. Right-2, wrect. Bottom-2 );
R2: = createrectrgn (wrect. Left + 2, wrect. Top + 2, wrect. Right, wrect. Bottom );
Combinergn (Region, R1, R2, rgn_or );
Deleteobject (R1 );
Deleteobject (R2 );
Setjavaswrgn (hwnd, region, true );
End;
// + JT
Dec (wrect. Right, 2 );
Dec (wrect. Bottom, 2 );
End; // + JT
}
Dcanvas. Brush. Style: = bsclear;
Dcanvas. Pen. Color: = fmenubordercolor;
Dcanvas. rectangle (wrect. Left, wrect. Top, wrect. Right, wrect. Bottom );
IfIsrighttoleftThen
Begin
Dcanvas. Pen. Color: = fficonbackcolor;
Dcanvas. moveTo (wrect. Right-3, wrect. Top + 2 );
Dcanvas. lineto (wrect. Right-2, wrect. Bottom-1 );
End
Else
Begin
Dcanvas. Pen. Color: = fficonbackcolor;
Dcanvas. rectangle (wrect. Left + 1, wrect. Top + 2, wrect. Left + 3, wrect. Bottom-1 );
End;
// + JT
Stretchblt (dcanvas. Handle, wrect. Left + 1, wrect. Top + 1, wrect. Right-wrect. Left-1, 2,
Dcanvas. Handle, wrect. Left + 1, wrect. Top + 3, wrect. Right-wrect. Left-1, 1, srccopy );
IfIswxpThen
Begin
Stretchblt (dcanvas. Handle, wrect. Left + 1, wrect. Bottom-3, wrect. Right-wrect. Left-1, 2,
Dcanvas. Handle, wrect. Left + 1, wrect. Top + 3, wrect. Right-wrect. Left-1, 1, srccopy );
Dcanvas. Pen. Color: = ffcolor;
Dcanvas. rectangle (wrect. Right-3, wrect. Top + 1, wrect. Right-1, wrect. Bottom-1 );
End;
// + JT
{Modify: conch 2004-11-04 the shadow is too ugly.
INC (wrect. Right, 2 );
INC (wrect. Bottom, 2 );
If not iswxp then // + JT
Begin // + JT
Dcanvas. Pen. Color: = fmenushadowcolor;
Dcanvas. rectangle (wrect. Left + 2, wrect. Bottom, wrect. Right, wrect. Bottom-2 );
Dcanvas. rectangle (wrect. Right-2, wrect. Bottom, wrect. Right, wrect. Top + 2 );
End; // + JT
}

 Finally
Releasedc (hwnd, WDC); // + JT
Dcanvas. Free;
Fsettingtransferwrng: = false;
 End;

End;

Related Article

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.