`
dato0123
  • 浏览: 940014 次
文章分类
社区版块
存档分类
最新评论

【翻译】Use a bitmap as a background image

 
阅读更多

原文链接

1: 使用自绘制列表控件

自定义的列表控件必须是自绘制的,因此需要在资源编辑器中设置LVS_OWNERDRAWFIXED标志,而且还必须在自定义的控件类中实现DrawItem函数。

2: 增加成员变量

当每一项都需要重绘的时候去重新加载位图或重新创建逻辑调色板的话,效率不高。因此我们增加成员变量来保存位图,逻辑调色板以及位图的尺寸信息。

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->protected:
CPalettem_pal;
CBitmapm_bitmap;
intm_cxBitmap,b_cyBitmap;

3: 增加成员函数来设置背景图片

SetBkImage函数首先做的是,如果位图和调色板已经被创建的话,就删除位图和调色板GDI对象(说明不是第一次调用)。

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->if(m_bitmap.m_hObject!=NULL)
m_bitmap.DeleteObject();
if(m_pal.m_hObject!=NULL)
m_pal.DeleteObject();

然后加载位图并且将位图连接到CBitmap对象上。在这里我们使用全局的::LoadImage()而不是CBitmap::LoadBitmap(),原因是我们需要访问到位图的DIBSECTION,而之所以需要DIBSECTION是因为我们要创建一个与位图使用的颜色相匹配的逻辑调色板。为什么要调色板?呵呵,如果你不建立并使用一个逻辑调色板的话,那么图片在256色的显示器上就会显得很阴暗。此外,为了后面的使用,我们也保存了位图的尺寸信息。

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->HBITMAPhBmp=(HBITMAP)::LoadImage(AfxGetInstanceHandle(),
lpszResourceName,IMAGE_BITMAP,
0,0,LR_CREATEDIBSECTION);
if(hBmp==NULL)
returnFALSE;
m_bitmap.Attach(hBmp);
BITMAPbm;
m_bitmap.GetBitmap(
&bm);
m_cxBitmap
=bm.bmWidth;
m_cyBitmap
=bm.bmHeight;

一旦我们有了位图集,我们就开始创建逻辑调色板。我们通过调用CBitmap::GetObject()函数来获得对DIBSECTION的访问,从而得到位图所使用的颜色数目。

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->//Createalogicalpaletteforthebitmap
DIBSECTIONds;
BITMAPINFOHEADER
&bmInfo=ds.dsBmih;
m_bitmap.GetObject(
sizeof(ds),&ds);

有的时候DIBSECTION 中的BITMAPINFOHEADER字段并没有指明它所使用的颜色数目,在这种情况下我们可以从它每个像素使用的位数来推断它的颜色数目,比如说,8位可以代表256个不同值,因此也就代表了256种颜色。类似的,16位就表明有64K种颜色.

颜色数目多于256的位图并没有颜色表。这种情况下我们简单地创建一个与设备环境兼容的halftone 调色板。一个halftone调色板就是一个包含各种不同颜色的一个样本集。这并不是最好的,但却是最简单的方法。

如果位图的颜色数目少于或等于256,我们就创建调色板。我们为位图分配足够的空间来保存它的颜色表,并且调用函数:: GetDIBColorTable来从位图中获得这个颜色表。我们还分配足够的内存来创建逻辑调色板,并且从位图的颜色表中拷贝所有的颜色实体。

在创建完调色板对象后,我们提前释放掉分配的内存块,并且让窗口无效,从而窗口可以使用新的图片来重画自己。
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->//Createahalftonepaletteifcolors>256.
CClientDCdc(NULL);//DesktopDC
if(nColors>256)
m_pal.CreateHalftonePalette(
&dc);
else
{
//Createthepalette
RGBQUAD*pRGB=newRGBQUAD[nColors];
CDCmemDC;
memDC.CreateCompatibleDC(
&dc);
memDC.SelectObject(
&m_bitmap);
::GetDIBColorTable(memDC,
0,nColors,pRGB);
UINTnSize
=sizeof(LOGPALETTE)+(sizeof(PALETTEENTRY)*nColors);
LOGPALETTE
*pLP=(LOGPALETTE*)newBYTE[nSize];
pLP
->palVersion=0x300;
pLP
->palNumEntries=nColors;
for(inti=0;i<nColors;i++)
{
pLP
->palPalEntry[i].peRed=pRGB[i].rgbRed;
pLP
->palPalEntry[i].peGreen=pRGB[i].rgbGreen;
pLP
->palPalEntry[i].peBlue=pRGB[i].rgbBlue;
pLP
->palPalEntry[i].peFlags=0;
}
m_pal.CreatePalette(pLP);
delete[]pLP;
delete[]pRGB;
}
Invalidate();

4: 修改DrawItem() 来处理图片

DrawItem()函数是用于绘制列表中的每一项的。我们在这个函数中绘制背景图片。由于背景图片应该完全地覆盖掉整个客户区,因此我们对剪切区域进行调整,使得它延展到客户区的右边缘。同样地,如果画列表的最后一项,剪切区域就应该扩展到客户区的下边缘。

然后是选择调色板(这只在设备支持调色板时有意义)。

背景图片是以一种平铺地方式进行绘制的,绘制图片时总是使用列表的第一项的左上角来作为参照。这就使得图片产生这样的效果:随着列表控件的内容的变化而滚动。

对原来的DrawItem()函数的另一个改变是只有当背景图片没有绘制时才绘制未被选中的项的背景

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->//Drawbitmapinthebackgroundifonehasbeenset
if(m_bitmap.m_hObject!=NULL)
{
CDCtempDC;
tempDC.CreateCompatibleDC(pDC);
tempDC.SelectObject(
&m_bitmap);
GetClientRect(
&rcClient);
CRgnrgnBitmap;
CRectrcTmpBmp(rcItem);
rcTmpBmp.right
=rcClient.right;
//Wealsoneedtocheckwhetheritisthelastitem
//Theupdateregionhastobeextendedtothebottomifitis
if(nItem==GetItemCount()-1)
rcTmpBmp.bottom
=rcClient.bottom;
rgnBitmap.CreateRectRgnIndirect(
&rcTmpBmp);
pDC
->SelectClipRgn(&rgnBitmap);
rgnBitmap.DeleteObject();
if(pDC->GetDeviceCaps(RASTERCAPS)&RC_PALETTE&&m_pal.m_hObject!=NULL)
{
pDC
->SelectPalette(&m_pal,FALSE);
pDC
->RealizePalette();
}
CRectrcFirstItem;
GetItemRect(
0,rcFirstItem,LVIR_BOUNDS);
for(inti=rcFirstItem.left;i<rcClient.right;i+=m_cxBitmap)
for(intj=rcFirstItem.top;j<rcClient.bottom;j+=m_cyBitmap)
pDC
->BitBlt(i,j,m_cxBitmap,m_cyBitmap,&tempDC,
0,0,SRCCOPY);
}
//Drawthebackgroundcolor
if(bHighlight)
{
pDC
->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
pDC
->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
pDC
->FillRect(rcHighlight,&CBrush(::GetSysColor(COLOR_HIGHLIGHT)));
}
elseif(m_bitmap.m_hObject==NULL)
pDC
->FillRect(rcHighlight,&CBrush(::GetSysColor(COLOR_WINDOW)));

5: WM_ERASEBKGND增加处理

当一张图片用作背景时,由于图片会画在背景上面,所以擦除背景并没有什么意义。擦除背景只会导致屏幕的闪烁,我们对WM_ERASEBKGND处理时,当位图对象合法时就返回true;

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->BOOLCMyListCtrl::OnEraseBkgnd(CDC*pDC)
{
if(m_bitmap.m_hObject!=NULL)
returnTRUE;
returnCListCtrl::OnEraseBkgnd(pDC);
}

6: 重写 OnNotify() 并处理列宽变化

当一列被resize后,只有新扩展出来的地方需要重新绘制,这就在背景图片上产生一个不好的效果。因此,当任何一列被resize后,我们应该在OnNotify函数中使控件的右边无效。

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->BOOLCMyListCtrl::OnNotify(WPARAMwParam,LPARAMlParam,LRESULT*pResult)
{
HD_NOTIFY
*pHDN=(HD_NOTIFY*)lParam;

//Thiscodeisforusingbitmapinthebackground
//Invalidatetherightsideofthecontrolwhenacolumnisresized
if(pHDN->hdr.code==HDN_ITEMCHANGINGW||pHDN->hdr.code==HDN_ITEMCHANGINGA)
{
if(m_bitmap.m_hObject!=NULL)
{
CRectrcClient;
GetClientRect(
&rcClient);
DWORDdwPos
=GetMessagePos();
CPointpt(LOWORD(dwPos),HIWORD(dwPos));
ScreenToClient(
&pt);
rcClient.left
=pt.x;
InvalidateRect(
&rcClient);
}
}
returnCListCtrl::OnNotify(wParam,lParam,pResult);
}

7:处理WM_QUERYNEWPALETTE & WM_PALETTECHANGED

当一个窗口准备开始接收输入焦点的时候,WM_QUERYNEWPALETTE消息就发送给它。这给窗口一个实现其逻辑调色板的机会,这样它就可以以最佳的形式展现自己。当系统调色板被改变时WM_PALETTECHANGED就被发送给窗口。如果我们不处理这些消息,而恰好另一个应用程序改变了系统调色板,那么我们的背景图片就会变得很难看。不幸地是,这两个消息都是发给顶层的窗口的。

OnQueryNewPalette首先检查它是否需要重新选择调色板。一旦它实现了逻辑调色板,它就让窗口无效。如果列表控件自己负责处理消息,那么就返回,不做进一步处理,否则OnPaletteChanged函数调用OnQueryNewPalette来实现调色板。

8:从顶层窗口转发调色板消息

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->voidCListViewDlg::OnPaletteChanged(CWnd*pFocusWnd)
{
CDialog::OnPaletteChanged(pFocusWnd);
m_listctrl.SendMessage(WM_PALETTECHANGED,(WPARAM)pFocusWnd
->m_hWnd);
}
BOOLCListViewDlg::OnQueryNewPalette()
{
CDialog::OnQueryNewPalette();
returnm_listctrl.SendMessage(WM_QUERYNEWPALETTE);
}


分享到:
评论

相关推荐

    Quickreport v5.05.1 for BC++ XE4 Full Source

    Transparent bands and background image property is a QRImage control placed on the report (not on a band). The control remains invisible but its bitmap is painted onto each page before other printing....

    Visual C++ 编程资源大全(英文源码 图形)

    04.zip Writing a bitmap to a BMP file 将一个位图写到BMP文件中(11KB)&lt;END&gt;&lt;br&gt;5,05.zip Bitmap background in MDI Client 在多文档客户程序中增加位图底图(4KB)&lt;END&gt;&lt;br&gt;6,06.zip Converting a ...

    VGScene 2.8 FULLSOURCE

    VGScene speeds the development of all graphical application, providing: a graphical editor integrated in IDE, graphical objects, simplify animation, advanced windows and controls, maximum performance,...

    BobBuilder_app

    Duplicate keys are stored as a WAH Bitmap Index for optimal storage and speed in access. Two mode of operation Flush immediate and Deferred ( the latter being faster at the expense of the risk of non-...

    VGScene_2.92.rar

    * Advanced animations techniques calculated in background thread. Easy to use, accuracy, minimal CPU usage and automatic FPS correction * VGScene provides for bitmap effects, however, they are ...

    VB编程资源大全(英文源码 表单)

    menu.zip This example shows how to change your applications menu apperance as in color and font.&lt;END&gt;&lt;br&gt;5 , dos-iface.zip This is an example of how to use skins in your program, and also using ...

    RxLib控件包内含RxGIF,全部源码及DEMO

    TPicClip represents a bitmap as the logical array of bitmaps and supports access by index. TFormPlacement allows to save and restore form size, position and window state in/from ini-file or Registry....

    Mastering_Perl_Tk_1st_ed_2002.pdf

    A table lists the standard options that can be applied to all types of button widgets, such as text, image, and command bindings. **4.3 Table of Options for Button-Type Widgets** This table provides...

    delphi 7 gif控件

    // Image.Parent.Invalidate or Image.Parent.Refresh to restore the background. // // This change was made as a result of a email correspondance with // // Tineke Kosmis (http://www.classe.nl/) which ...

    VB编程资源大全(英文控件)

    Background Pictures and Icons can be added with ease&lt;END&gt;&lt;br&gt;24,pktextline.zip Textbox with modern design&lt;END&gt;&lt;br&gt;25,DirScanner.zip DirScanner is a free ActiveX control designed to scan ...

    FlexGraphics_V_1.79_D4-XE10.2_Downloadly.ir

    type can now be defined as a sequence: TEnum = ( eOne, eTwo ); . . . EnumProp.SetItem(integer(eOne), 'One'); EnumProp.SetItem(integer(eTwo), 'Two'); If some items are skipped when filling data ...

    Android画板开发之添加背景和保存画板内容为图片

    // Attempt to use a display list if requested. if (canvas.isHardwareAccelerated() && mAttachInfo != null && mAttachInfo.mHardwareRenderer != null) { mBackgroundRenderNode = getDrawableRenderNode...

    Bmp To Mif 转换器

    Run this converter in command prompt using the name of the BMP file you created as a command-line parameter. // For example: // bmp2mif foo.bmp // 4. The program generates two files: // image....

    FastReport.v4.15 for.Delphi.BCB.Full.Source企业版含ClientServer中文修正版支持D4-XE5

    FastReport® provides all the tools necessary for developing reports, including a visual report designer, a reporting core, and a preview window. It can be used in Embarcadero (ex Borland and ...

    TMS Pack for FireMonkey2.3.0.1

    TMS Pack for FireMonkey contains components for use in user interfaces designed with the Embarcadero FireMonkey framework. The components have been designed from the ground up based on the core ...

    PT80-NEAT开发指南v1.1

    NEAT 开 发 指南 文档 适用于 PT80 系列 移动数据终端 版本记录 版本号 版本描述 发布日期 V 1.0 初始版本。 2012-04-12 V1.1 修改前三章内容 2012-09-25 目录 第一章 关于本手册.....................................

Global site tag (gtag.js) - Google Analytics