注册 | 登录
收藏 | 帮助
热门文章
编辑推荐
相关文章  
Win XP中震荡波后应采取的措施
Win XP SP2拖放IE窗口可能引发黑
查杀耗CPU资源的Explored病毒
杀毒软件如何被XP SP2的安全中心
黑客入侵Win XP常用七大招数
黑客入侵WindowsXP系统常用七大招
windows XP的八大安全策略
封杀Windows XP的共享漏洞
快速干掉感染Internet Explorer的
WinXP/2K鲜为人知的安全命令
您现在的位置: 顶尖设计 >> IT学院 >> 编程开发 >> Delphi >> 文章正文
修正XPMenu的两个Bug
作者:nhconch  来源:csdn  点击:  更新:2006-12-19
简介:
XPMenu是大名鼎鼎的Dephi第三方界面控件,最近在使用中发现了几个Bug,并对其中的两个进行修正。

1、首先,是绘制菜单和工具栏图标时,会将图像白色部分作为透明色,导致图像缺损非常难看,如下图所示:
XPMenu图标透明Bug示图
  查看XPMenu的源代码,图标是通过TXPMenu.DrawIcon函数绘制的,函数内计算了图标显示的位置、调用GrayBitmap、DimBitmap、DrawBitmapShadow等函数对图像进行了处理,并将图像的Transparent设为true,再查看GrayBitmap、DimBitmap、DrawBitmapShadow函数并没有发现会导致透明色计算错误的代码。再往回找,终于在TXPMenu.MenueDrawItem和TXPMenu.ToolBarDrawButton里发现了问题,先来看看TXPMenu.MenueDrawItem:

procedure TXPMenu.MenueDrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
  Selected: Boolean);
beign
.....
  //-------
  if HasBitmap then
    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;


  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;
     // 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}
    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; //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;

  很明显,除了XPMenu的作者之外,+jt、Asher和X均对代码进行过修改,问题就出在+jk的修改的这段代码里,它先用B(TBitmap).Canvas.Pixels[0, B.Height - 1]处的颜色填充了整个B,然后再把要显示的图标画到B里去,后面会调用DrawIcon把图标显示出来,可惜+jt计算错误,当时的B(TBitmap).Canvas.Pixels[0, B.Height - 1]值正是$FFFFFF(白色),以ILD_Transparent参数调用ImageList_DrawEx时会把原图标底色(比如上图的粉红色)去掉,那么DrawIcon绘制的图标底色就是白色的,最后图标所有白色部分被挖空了。+jt真是好心做坏事了。
  原因找到了,现在直接把+jt那部分代码去掉即可。原程序变为:

procedure TXPMenu.MenueDrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect;
  Selected: Boolean);
beign
.....
  //-------
  if HasBitmap then
    begin
      B.Width := FMenuItem.Bitmap.Width;
      B.Height := FMenuItem.Bitmap.Height;
{Modify: Conch 2004-12-16 画出的图标透明颜色有错
  // +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;


  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 画出的图标透明颜色有错
     // 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}
    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;
{Modify: Conch 2004-12-16 画出的图标透明颜色有错
      //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);

[1] [2] 下一页






  • 上一篇文章:
  • 下一篇文章:
  • 分享此文:该页面添加到 Mister Wong 添加到雅虎Yahoo!收藏 Add to:Del.icio.us Post to Furl Digg this 添加到Google书签 reddit spurl blogmarks 365Key 评论  收藏  分享  打印
     我来说两句
    姓名:       验证码:   
    主页: 
    评分: 1分 2分 3分 4分 5分
    本频道近期热评文章:
      关于我们 | 联系我们 | 站点地图 | 广告投放 | 友情链接 | 在线留言 | 版权申明
    版权所有 © 2004-2007 顶尖设计(bobd.cn)
    未经授权禁止转载,摘编,复制本站内容或建立镜像. 沪ICP备07504942号 
    网络110
    报警服务