XpMenu is a famous DEPHI third-party interface control, recently found several bugs, and corrections two of them. 1. First, when the menu and toolbar icon are drawn, the white part is used as transparent colors, resulting in the image defect, as shown below: View the source code of XpMenu, the icon is drawn through the TXPMENU.DRAWICON function, functions The location of the icon display is calculated, and the graybitmap, dimbitmap, drawbitmapshadow, etc. are called, and the image's Transparent is set to True, then view the graybitmap, dimbitow, the drawbitmapshadow function does not find the code that causes transparent color calculation errors. . Go back and finally found the problem in TXPMenu.menueDrawItem and TXPMENU.ToolBardRawbutton, first take a look at TXPMenu.MenueDrawItem:
Procedure txpmenu.menueDRawItem (Sender: Tobject; Acanvas: tcanvas; allvas: TRECT; SELECTED: BOOLEAN); beign ..... // ------- if Hasbitmap The 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" 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; if HasimglstbitMap dam {$ ifdef Ver5u} if fmenuitem.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.bru Sh.color; // jt b.canvas.brush.color: = b.canvas.pixels [0, b.height - 1]; // "Todd asher" 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); Else {$ ENDIF} if FMenuItem.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; //aacanvas.pixels[2, 2]; // jt b.canvas.brush.color: = b.canvas.pixels [0, B.HEIGHT - 1 ]; // "Todd asher" B.canvas.FillRect (RECT (0, 0, B.Width, B.HEight); ImageList_Drawex (ImglistHandle, ImgIndex, B.canvas.Handle, 0 , 0, 0, 0 ,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.IgHTTOLEFT); ... END; It is obvious, except for the author of XpMenu, JT, Asher and X are The code has been modified, and the problem is in this code in JK, it first filled the entire B with B (tbitmap) .canvas.pixels [0, b.height - 1], then put it again To display the icon to B, then call Drawicon to display the icon, but unfortunately JT calculation errors, the B (Tbitmap) .canvas.pixels [0, B.HEight - 1] is $ ffffff ( White), remove the original icon floor color (such as the pink of the figure above) with the ILD_TRANSPARENT parameter, then the icon drawn of Drawicon is white, and the last icon all white parts are taken empty. JT is really good to do bad things. The reason is found, and now you can remove the part of the JT directly. The original program becomes:
Procedure txpmenu.menueDRawItem (Sender: Tobject; Acanvas: tcanvas; allvas: TRECT; SELECTED: BOOLEAN); beign ..... // ------- if Hasbitmap The begin B.Width: = fmenuitem.bitmap. Width; b.height: = fMenuitem.bitmap.height; {modify: Conch 2004-12-16 Draw the icon transparent color is wrong // JT //b.canvas.brush.color: = ftransparentColor; // acanvas .Brush.color; b.canvas.brush.color: = b.canvas.pixels [0, b.height - 1]; // "Todd asher" B.canvas.FillRect (RECT) 0, 0, B.Width, B.Height); fMenuItem.bitmap.transparent: = true; fmenuitem.bitmap.transparentmode: = tMAUTO;} B.canvas.draw (0, FMenuItem.bitmap); // jt end; if HasImgLstBitmap then begin {$ IFDEF VER5U} if FMenuItem.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: Conch 2004-12-16 Out of the icon transparent color is wrong // b.canvas.brush.color: = ftransparentColor; // acanvas.brush.color; // jt b.canvas.brush.color: = b.canvas.pixels [0, B .Height - 1]; // "Todd asher" B.canvas.FillRect (RECT (0, 0, B.Width, B.HEight); ImageList_Drawex (ImglistHandle, ImgIndex, B.canvas .Handle, 0, 0, 0, clnone, clnone, ild_transparent;} imaglist_drawex (imglisthandle, imgindex, b.canvas.handle, 0, 0, 0, 0, clon, clyn, ild_normal; // conch end Else {$ ENDIF} if fmenuitem.parent.getParentMenu.Images <> nil dam imglisthandle: =
FMenuItem.Parent.GetParentMenu.Images.Handle; ImgIndex: = FMenuItem.ImageIndex; B.Width: = FMenuItem.Parent.GetParentMenu.Images.Width; B.Height: = FMenuItem.Parent.GetParentMenu.Images.Height; {Modify: Conch 2004-12-16 Draw the icon transparent color is wrong //b.canvas.brush.color: = ftransparentcolor; //acanvas.pixels[2, 2]; // jt b.canvas.brush.color: = B. Canvas.Pixels [0, B.HEIGHT - 1]; // "Todd asher" 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.Isttoleft; ...... End; TXPMENU.ToolBardRawbutton is also the same.
procedure TXPMenu.ToolBarDrawButton (Sender: TToolBar; Button: TToolButton; State: TCustomDrawState; var DefaultDraw: Boolean); begin if CanDraw then begin {CanDraw} {Modify: Conch 2004-12-16 drawn wrong icon Transparent Color @ B.canvas.brush.color: = transparentcolor; // acanvas.brush.color; // jt b.canvas.brush.color: = b.canvas.pixels [0, B.HEight - 1]; // " Todd asher " 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, clyn, clnone, ild_normal); // conch ...... END; 2, the second problem is that the shadow of the menu is too hidden, which is a fixed layer of gray block (of course, refers to WinXP's previous system), as shown: Menu shadow is drawn by the TXPMENU.DRAWWINDOWBORDER function. Here, you can see that JT has been modified, but JT's annotation is a bit special, and you can't see those original code in the author, those who have changed it is JT, but it is certain that there is a lot of hard work. This function turns off the 3D border of Windows and turns into a flat officeXP style menu. If you want to change the shadow effect that is mixed with the background pixel menu, you must change the source code, but the purpose of using the third party control is to facilitate the convenience, if so, there is too violated. . So I used a compromised approach here to reduce the gray area, so it looks like it. The final effect is as follows: The modified TXPMENU.DRAWWINDOWBORDER function:
Procedure TXPMenu.drawWindowborder (hwnd: hwnd; isrighttoleft: boolean); Var WRECT: TRECT; DCANVAS: Tcanvas; WDC: HDC; // Jt RegionType: Integer; // JT R1, R2, WR, Region: hRGN; / / JT RGNR: TRECT; // JTBEGIN IF (hwnd <= 0) or (FSETTINGWINDOWRNG) THEN BEGIN EXIT; End; // JT WDC: = getWindowdc (hwnd); // GetDesktopWindow IF WDC = 0 THEN EXIT; // jt fsettingWindowrng: = true; // jt dcanvas: = tcanvas.create; try dcanvas.handle: = WDC; // jt getWindowRect (hwnd, wRECT); // jt wRect.right: = WRECT. Right-whect.Lect.Bottom: = WRECT.BOTTOM-WRECT.TOP; WRECT.TOP: = 0; WRECT.TOP: = 0; if getwindowlong (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 Drawing shadow is too ugly if not iswxp the Begin WR : = CreateRectrGN (0, 0, 0); RegionType: = getWindowRgn (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, 0); R1: = CreateRectrgn (WRECT.RIGT, 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); setWindowRgn (hwnd, region, true); end; // jt dec (WRECT.Right, 2); DEC (WRECT.BOTTOM, 2); end; // jt} dcanvas.brush.style: = bsclear; dcanvas.pen.color: = fmenubordercolor;