2018年7月10日
2014年9月18日
解決方法:
ShowDropDown();之后SetCursor(LoadCursor(NULL, IDC_ARROW));即可
2013年3月17日
2013年2月27日
有時(shí)候下拉框(MFC標(biāo)準(zhǔn)叫組合框,CComboBox)中條目文本很多,超過(guò)了下拉框的寬度,如果不加設(shè)置的話(huà),超過(guò)的部分文本將無(wú)法顯示,查找MSDN,發(fā)現(xiàn)解決方法,代碼如下:
代碼
// The pointer to my combo box.
extern CComboBox* pmyComboBox;
// Set the height of every item so the item
// is completely visible.
CString str;
CSize sz;
int dx=0;
CDC* pDC = pmyComboBox->GetDC();
for (int i=0;i < pmyComboBox->GetCount();i++)
{
pmyComboBox->GetLBText( i, str );
sz = pDC->GetTextExtent(str);
// Only want to set the item height if the current height
// is not big enough.
if (pmyComboBox->GetItemHeight(i) < sz.cy)
pmyComboBox->SetItemHeight( i, sz.cy );
// Only want to set the item width if the current width
// is not big enough.
if (pmyComboBox->GetDroppedWidth() < sz.cx)
{
pmyComboBox->SetDroppedWidth(sz.cx + 20);
}
}
pmyComboBox->ReleaseDC(pDC);
效果圖:

2012年7月15日
2012年4月25日
1. 把你的虛擬網(wǎng)卡VMnet8(在Win系統(tǒng)的網(wǎng)上鄰居里)設(shè)置為自動(dòng)獲得IP、自動(dòng)獲得DNS服務(wù)器,啟用。
2.
把你虛擬機(jī)中操作系統(tǒng)的Editing Auto Ethernet->IPV4 Setting 設(shè)置成如上圖所示。
有些Linux可以如下設(shè)置:“本地連接”也設(shè)置為自動(dòng)獲得IP、自動(dòng)獲得DNS服務(wù)器(在虛擬機(jī)中,右鍵“本地連接”-雙擊“Internet 協(xié)議”,看看是不是自動(dòng)的吧!固定IP的也在這里改!)
3.當(dāng)然是將虛擬機(jī)的上網(wǎng)方式選為NAT咯。
右鍵你要設(shè)置的虛擬機(jī)選“設(shè)置”(因?yàn)橛械牟恢固摂M一臺(tái)),在“硬件”中選“以太網(wǎng)”, 將右邊的網(wǎng)絡(luò)連接改為NAT-確定。
4.點(diǎn)菜單欄里的“編輯”-選“虛擬網(wǎng)絡(luò)設(shè)置”,先將“自動(dòng)橋接”給去掉(去掉鉤鉤),再選“DHCP”開(kāi)啟DHCP服務(wù),點(diǎn)“開(kāi)始”-應(yīng)用,再按同樣的方法開(kāi)啟“NAT”的功能。
5.最重要的是你的兩個(gè)服務(wù)必須開(kāi)啟:VMware DHCP Service 和VMware NAT Service。
具體操作如下: 開(kāi)始---設(shè)置--控制面板---管理工具---服務(wù),確保 VMware DHCP Service 和VMware NAT Service 服務(wù)已經(jīng)啟動(dòng)
//====================================另外的方法
Ubuntu虛擬機(jī)共享主機(jī)上網(wǎng)
WinXP+VMware WorkStation+Ubuntu7.10
一.Bridged方式共享上網(wǎng)
1.設(shè)置Ubuntu的網(wǎng)絡(luò)連接方式為Bridged
2.共享ADSL連接
ADSL連接屬性中選中“Internet連接共享”,下拉列表中然后選擇“本地連接”,系統(tǒng)會(huì)自動(dòng)把“本地連接”設(shè)置為192.168.0.1。注意此設(shè)置會(huì)在斷開(kāi)連接并重啟后才生效
3.Ubuntu網(wǎng)絡(luò)設(shè)置
IP:192.168.0.X
網(wǎng)關(guān):192.268.0.1
DNS:192.168.0.1(系統(tǒng)->系統(tǒng)管理->網(wǎng)絡(luò)->DNS)
二.NAT方式共享上網(wǎng)
1.設(shè)置Ubuntu的網(wǎng)絡(luò)連接方式為NAT
2.開(kāi)啟VMware DHCP Service和VMware NAT Service兩個(gè)服務(wù)
3.Ubuntu中網(wǎng)絡(luò)設(shè)置為自動(dòng)配置(DHCP)或者手動(dòng)設(shè)置IP及DNS
手動(dòng)設(shè)置方法:
1.XP中ipconfig,得到VMnet8的IP為192.168.93.1
2.Ubuntu中設(shè)置網(wǎng)絡(luò)IP為192.168.93.X(X為3-254,網(wǎng)上很多人說(shuō)只能是128-254,自動(dòng)分配時(shí)一般也是128,但經(jīng)驗(yàn)證3-254都行,DNS設(shè)置為192.168.93.2
以上方法均經(jīng)驗(yàn)證,絕無(wú)多余步驟。
2012年1月10日
1、 Dump文件放在哪里?
Dump文件不用非要放在你編譯出來(lái)的位置,你完全可以建立一個(gè)新的文件夾來(lái)放它。但若不是存放在編譯出來(lái)的位置,需要將編譯生成的PDB文件拷貝到Dump文件目錄,或是利用VS2005打開(kāi)Dump文件后,設(shè)置PDB文件路徑。
2、 如何恢復(fù)當(dāng)時(shí)的現(xiàn)場(chǎng)?可能你要問(wèn),怎么可能,這個(gè)dump文件可是用戶(hù)發(fā)給我的,我不可能去用戶(hù)家里調(diào)試吧?這個(gè)恢復(fù)現(xiàn)場(chǎng)可不是指的非要到那臺(tái)機(jī)器上去,而是要把產(chǎn)生dump文件對(duì)應(yīng)的二進(jìn)制文件拿到。
但是恢復(fù)現(xiàn)場(chǎng)需要所有的二進(jìn)制文件都要對(duì)應(yīng),你一定要有導(dǎo)致用戶(hù)崩潰的那些Exe和DLL。既然是你發(fā)布的程序,Exe文件當(dāng)然你會(huì)有。所以這里只考慮DLL就行了。
Dump文件中記錄了所有DLL文件的版本號(hào)和時(shí)間戳,所以你一定可以同過(guò)某種途徑拿到它。如果你能從用戶(hù)那里拿到最好,如果不方便,用戶(hù)不可能用的是我們平常不常用的操作系統(tǒng),所以找個(gè)有對(duì)應(yīng)系統(tǒng)的機(jī)器一般都會(huì)有。但是記住不僅是文件名稱(chēng)要一致,還要核對(duì)版本和時(shí)間戳,如果不同一樣沒(méi)有辦法用。
如果客戶(hù)用了某個(gè)特殊的補(bǔ)丁怎么辦?
其實(shí)這個(gè)問(wèn)題也很好解決,只要它不阻礙閱讀堆棧,就不用管它,調(diào)試Dump和運(yùn)行程序不一樣,缺少一兩個(gè)DLL沒(méi)有任何問(wèn)題。
3、 如果真的需要怎么辦?符號(hào)文件現(xiàn)在主要是指PDB文件。
如果沒(méi)有符號(hào)文件,那么調(diào)試的時(shí)候可能導(dǎo)致堆棧錯(cuò)誤。
如果你丟失了這個(gè)發(fā)布版本中你編譯出來(lái)的那些exe和DLL的PDB,那么這個(gè)損失是嚴(yán)重的,重新編譯出來(lái)的版本是不能使用的。
我自己的DLL都有了,可是缺的是系統(tǒng)的DLL的對(duì)應(yīng)PDB文件怎么辦?圖1.4中已經(jīng)介紹了方法。微軟在它的符號(hào)數(shù)據(jù)庫(kù)上為我們提供了所有的PDB文件,還有部分非關(guān)鍵DLL。設(shè)置好后程序?qū)⒆詣?dòng)下載需要的PDB及DLL文件。
4、 拿到需要的文件了,這些文件應(yīng)該放在哪里?符號(hào)數(shù)據(jù)庫(kù)中的文件不用動(dòng),把其它的exe和DLL、PDB文件放在dump文件目錄里就行了。
5、 我用的是VS2005,明明有源代碼,為什么顯示不了?這個(gè)是dump調(diào)試的最頭痛問(wèn)題,代碼可能已經(jīng)改過(guò)了,即使你從SVN拿到當(dāng)時(shí)的版本,時(shí)間戳也是錯(cuò)的,VS2005就是不讓你顯示代碼。其實(shí)只要在
Tools/Options,Debugging/General中去掉
Require source files to exactly match the original version的復(fù)選就行了。
前言:利用drwtsn32或NTSD進(jìn)行程序崩潰處理,都可以生成可用于調(diào)試的dmp格式文件。使用VS2005打開(kāi)生成的DMP文件,能很方便的找出BUG所在位置。本文將討論以下內(nèi)容:
1、 程序編譯選項(xiàng)
2、 利用VS2005 分析dump文件
3、 常見(jiàn)問(wèn)題討論
一、 程序編譯選項(xiàng)
PDB files contains all debug information like type definition and function prototype. When application crashes, we need the PDB files to analyze the root cause, so make sure these PDB files will be created when building it. You must do the following setting:
C/C++/General/Debug Information Format=Program Database (/Zi).

圖1.1 調(diào)試信息格式
Linker/Debugging/Generate Program Database File=”Name and location of your PDB files”

圖1.2 PDB文件輸出路徑
PDB文件路徑最好設(shè)置在同一個(gè)文件夾中,這樣方便dmp文件調(diào)試時(shí)調(diào)用。
調(diào)試時(shí),所有的PDB文件和源文件必須嚴(yán)格匹配(the PDB files should be the one generated by build the source code),并存儲(chǔ)在一個(gè)安全的位置。當(dāng)客戶(hù)報(bào)告了一個(gè)錯(cuò)誤時(shí),你需要這些文件來(lái)幫忙以便定位錯(cuò)誤于源代碼中并解決問(wèn)題。
二、 VS2005 分析dump文件
In this simple application, there is an unhandled Access Violation Reading exception, because GetNameFromDatabase returns a NULL pointer, and this pointer is passed into IsPrefix and then it’s used directly without NULL pointer checking.

圖1.3 演示代碼
利用Release模式編譯該測(cè)試程序,在客戶(hù)機(jī)上運(yùn)行該程序,將根據(jù)NTSD設(shè)置生成相對(duì)應(yīng)的DMP格式文件。
可以使用Visual Studio.Net、NTSD或是其他的調(diào)試工具對(duì)DMP格式文件進(jìn)行分析。
l Start Visual Studio.Net
Click File/Open Solution and make sure the files of type is *.dmp then click Open.

圖1.3 Open Dump File (GUI)
l Set Symbol Path
Click Tools/Options, Debugging/Symbols,增加PDB文件路徑。若調(diào)試的程序需要微軟基礎(chǔ)庫(kù)的PDB信息,可以增加一個(gè)路徑為:
http://msdl.microsoft.com/download/symbols
在界面下方Cache Symbol From symbol…選擇本地存儲(chǔ)這些Symbols的路徑。

圖1.4 Symbol Path
如果DMP文件沒(méi)有放入本身PDB文件所在目錄,也可以在此處增加一個(gè)本地目錄。點(diǎn)OK后,VS2005將從網(wǎng)絡(luò)中下載所需要的Symbols,需要等待一段時(shí)間。如果是多次調(diào)試同一個(gè)程序錯(cuò)誤所生成的DMP文件,可以在對(duì)話(huà)框中選擇“Search the above locations only when symbols are loaded manually”。從而可以節(jié)省網(wǎng)絡(luò)帶寬。
l Set Source code path
Open Solution Property Pages and set the source code path.

圖1.5 屬性菜單

圖1.6 Debug Source Files
l Start to Debug the Dump File
Click the Debug menu, it will ask you to save as a solution, save it. Then it will go to the line which caused the crash of your application.

圖1.7 調(diào)試窗口,定位到源代碼
三、 常見(jiàn)問(wèn)題討論
1、 Dump文件放在哪里?
Dump文件不用非要放在你編譯出來(lái)的位置,你完全可以建立一個(gè)新的文件夾來(lái)放它。但若不是存放在編譯出來(lái)的位置,需要將編譯生成的PDB文件拷貝到Dump文件目錄,或是利用VS2005打開(kāi)Dump文件后,設(shè)置PDB文件路徑。參照?qǐng)D1.4。
2、 如何恢復(fù)當(dāng)時(shí)的現(xiàn)場(chǎng)?
可能你要問(wèn),怎么可能,這個(gè)dump文件可是用戶(hù)發(fā)給我的,我不可能去用戶(hù)家里調(diào)試吧?這個(gè)恢復(fù)現(xiàn)場(chǎng)可不是指的非要到那臺(tái)機(jī)器上去,而是要把產(chǎn)生dump文件對(duì)應(yīng)的二進(jìn)制文件拿到。
但是恢復(fù)現(xiàn)場(chǎng)需要所有的二進(jìn)制文件都要對(duì)應(yīng),你一定要有導(dǎo)致用戶(hù)崩潰的那些Exe和DLL。既然是你發(fā)布的程序,Exe文件當(dāng)然你會(huì)有。所以這里只考慮DLL就行了。
Dump文件中記錄了所有DLL文件的版本號(hào)和時(shí)間戳,所以你一定可以同過(guò)某種途徑拿到它。如果你能從用戶(hù)那里拿到最好,如果不方便,用戶(hù)不可能用的是我們平常不常用的操作系統(tǒng),所以找個(gè)有對(duì)應(yīng)系統(tǒng)的機(jī)器一般都會(huì)有。但是記住不僅是文件名稱(chēng)要一致,還要核對(duì)版本和時(shí)間戳,如果不同一樣沒(méi)有辦法用。
如果客戶(hù)用了某個(gè)特殊的補(bǔ)丁怎么辦?
其實(shí)這個(gè)問(wèn)題也很好解決,只要它不阻礙閱讀堆棧,就不用管它,調(diào)試Dump和運(yùn)行程序不一樣,缺少一兩個(gè)DLL沒(méi)有任何問(wèn)題。
3、 如果真的需要怎么辦?
符號(hào)文件現(xiàn)在主要是指PDB文件。
如果沒(méi)有符號(hào)文件,那么調(diào)試的時(shí)候可能導(dǎo)致堆棧錯(cuò)誤。
如果你丟失了這個(gè)發(fā)布版本中你編譯出來(lái)的那些exe和DLL的PDB,那么這個(gè)損失是嚴(yán)重的,重新編譯出來(lái)的版本是不能使用的。
我自己的DLL都有了,可是缺的是系統(tǒng)的DLL的對(duì)應(yīng)PDB文件怎么辦?圖1.4中已經(jīng)介紹了方法。微軟在它的符號(hào)數(shù)據(jù)庫(kù)上為我們提供了所有的PDB文件,還有部分非關(guān)鍵DLL。設(shè)置好后程序?qū)⒆詣?dòng)下載需要的PDB及DLL文件。
4、 拿到需要的文件了,這些文件應(yīng)該放在哪里?
符號(hào)數(shù)據(jù)庫(kù)中的文件不用動(dòng),把其它的exe和DLL、PDB文件放在dump文件目錄里就行了。
5、 我用的是VS2005,明明有源代碼,為什么顯示不了?
這個(gè)是dump調(diào)試的最頭痛問(wèn)題,代碼可能已經(jīng)改過(guò)了,即使你從SVN拿到當(dāng)時(shí)的版本,時(shí)間戳也是錯(cuò)的,VS2005就是不讓你顯示代碼。其實(shí)只要在
Tools/Options,Debugging/General中去掉
Require source files to exactly match the original version的復(fù)選就行了。
2011年10月21日
映射表類(lèi)(CMap)是MFC集合類(lèi)中的一個(gè)模板類(lèi),也稱(chēng)作為“字典”,就像一種只有兩列的表格,一列是關(guān)鍵字,一列是數(shù)據(jù)項(xiàng),它們是一一對(duì)應(yīng)的。關(guān)鍵字是唯一的,給出一個(gè)關(guān)鍵字,映射表類(lèi)會(huì)很快找到對(duì)應(yīng)的數(shù)據(jù)項(xiàng)。映射表的查找是以哈希表的方式進(jìn)行的,因此在映射表中查找數(shù)值項(xiàng)的速度很快。映射類(lèi)最適用于需要根據(jù)關(guān)鍵字進(jìn)行快速檢索的場(chǎng)合,我們的程序中就用映射表來(lái)保存計(jì)時(shí)器標(biāo)志值和類(lèi)實(shí)例指針,用計(jì)時(shí)器的標(biāo)志值作為關(guān)鍵字。
他這個(gè)有點(diǎn)像數(shù)組,比如你要查找a[index],不必先遍歷前面的index個(gè)元素,只不過(guò)數(shù)組的下標(biāo)是哈希表鍵值,它是以鍵值對(duì)的形式出現(xiàn)的。舉個(gè)例子來(lái)說(shuō)吧,公司的所有職員都有一個(gè)工號(hào)和自己的姓名,工號(hào)就是姓名的關(guān)鍵字,給出一個(gè)工號(hào),就可以很快的找到相應(yīng)的姓名。
舉例如下:
1、定義一個(gè)CMAP,向這個(gè)CMAP中增加數(shù)據(jù)項(xiàng)(鍵-值對(duì))。
CMap<CString, LPCTSTR, CString, LPCTSTR>m_ItemMap;
CString strKey = _T(""), str = _T("");
int i;
for(i = 0; i < 5; i++)
{
strKey.Format("%d", i); //這個(gè)是鍵
str.Format("A%d", i); //鍵對(duì)應(yīng)的值
m_ItemMap.SetAt(strKey, str);
}
2、遍歷正個(gè)CMAP的常用方法。
POSITION pos = m_ItemMap.GetStartPosition();
while(pos)
{
m_ItemMap.GetNextAssoc(pos, strKey, str);
cout<< strKey<< ":"<< str<< endl;
}
3、在CMAP中查找相應(yīng)的數(shù)據(jù)項(xiàng)。
CString pReset;
if(m_ItemMap.Lookup("1", pReset))
{
cout<<pReset<<endl;
}
=======================================================================現(xiàn)在,我們來(lái)學(xué)習(xí)MFC中,最常用的數(shù)據(jù)結(jié)構(gòu)中的最后一個(gè)CMap模板。之前,我們已經(jīng)依次學(xué)完了CArray,CList,并且也對(duì)它們進(jìn)行了初步的剖析。
其實(shí),我一直認(rèn)為CMap是最簡(jiǎn)單的一個(gè)數(shù)據(jù)類(lèi)型,如果說(shuō),大家對(duì)這個(gè)數(shù)據(jù)類(lèi)型產(chǎn)生不良感覺(jué)的話(huà),大多是因?yàn)閷?duì)Hash表的陌生。
顯然,CMap就是對(duì)Hash表的一種實(shí)現(xiàn)。對(duì)于Hash表來(lái)說(shuō),我們需要提供成對(duì)的Key與Value進(jìn)行操作,其實(shí),也就是將我們?nèi)粘J褂玫臄?shù)組下標(biāo)替換成現(xiàn)在Key,至于MFC是采用了什么樣的散列函數(shù),我們不必知道。
Hash表可以認(rèn)為是數(shù)組的一種優(yōu)化,或者說(shuō)是對(duì)數(shù)組缺陷的一種彌補(bǔ),因?yàn)槲覀冎溃瑪?shù)組在具備了高效存取性能的同時(shí),無(wú)法動(dòng)態(tài)的調(diào)整自身的大小,又嚴(yán)重的影響了它的使用效果。這給了Hash表可乘之機(jī),Hash表總是使用了某種算法盡可能的來(lái)達(dá)到將成對(duì)的元素存儲(chǔ)到一個(gè)額定的離散的內(nèi)存空間,它既繼承了鏈表對(duì)自身的動(dòng)態(tài)調(diào)整,又盡可能的使讀寫(xiě)維持在高速的水平,當(dāng)然無(wú)論如何還是要比數(shù)組慢的多。
如果你非要讓我告訴你,Hash表是什么樣的一個(gè)數(shù)據(jù)結(jié)構(gòu)的話(huà),很遺憾,我無(wú)法準(zhǔn)確的描述,這就相當(dāng)于你問(wèn)我“鳳凰是什么樣子”,不過(guò)我可以告訴你孔雀的樣子。常用的Hash表非常像一個(gè)十字?jǐn)?shù)組,似乎十字?jǐn)?shù)組又成為了眾多讀者的障礙,如果你暫時(shí)還不能理解的話(huà),請(qǐng)你去翻閱Hash表的詳細(xì)論述,當(dāng)然你也可以在不久之后,在本處看到這些經(jīng)典數(shù)據(jù)結(jié)構(gòu)的精講。
現(xiàn)在,我們來(lái)看一個(gè)CMap的用法,至于它的參數(shù),你可以看本空間一篇專(zhuān)門(mén)描述CArray,CList以及CMap參數(shù)用法的文章《CArray,CList,CMap如何實(shí)化(實(shí)例化)》。下面是我自己編寫(xiě)的例子:
class Point
{
public:
Point()
{
m_x = 0;
m_y = 0;
}
Point(int x, int y)
{
m_x = x;
m_y = y;
}
public:
int m_x;
int m_y;
};
typedef CMap<const char*, const char*, Point, Point&> CMapPnt; //請(qǐng)?jiān)谑褂弥岸x
int main()
{
Point elem1(1, 100), elem2(2, 200), elem3(3, 300), point;
CMapPnt mp;
// insert 3 elements into map, #1
mp.SetAt("1st", elem1);
mp.SetAt("2nd", elem2);
mp.SetAt("3th", elem3);
// search a point named "2nd" from map #2
mp.Lookup("2nd", point);
printf("2nd: m_x: %d, m_y: %d\n", point.m_x, point.m_y);
// insert a new pair into map #3
Point elem4(4, 400);
mp["4th"] = elem4;
cout<<"count: "<<mp.GetCount()<<endl;
// traverse the entire map #4
size_t index = 0;
const char* pszKey;
POSITION ps = mp.GetStartPosition();
while( ps )
{
mp.GetNextAssoc(ps, pszKey, point);
printf("index: %d, m_x: %d, m_y: %d\n", ++index, point.m_x, point.m_y);
}
return 0;
}
代碼中,我已經(jīng)給出了一些注釋?zhuān)彝瑯咏ㄗh讀者們,用英文在代碼中注釋?zhuān)@樣的好處實(shí)在是太多了。尤其在代碼需要在不同編碼的操作系統(tǒng)上調(diào)試的時(shí)候。
對(duì)于CMap這個(gè)類(lèi),我不得不著重啰嗦一下的是:遍歷操作以及取下標(biāo)【】操作,當(dāng)然還有那個(gè)令很多人困惑不已的ARG_KEY到底應(yīng)該如何選擇的問(wèn)題。
遍歷,看注釋#4,至于POSITION的含義,請(qǐng)?jiān)诒究臻g,查看其它文章。先使用GetStartPosition()函數(shù)獲得表頭的位置,然后,我們可以使用GetNextAssoc函數(shù)來(lái)遍歷。GetNextAssoc(POSITION& rNextPosition, KEY& rKey, VALUE& rValue)函數(shù)的參數(shù)值得說(shuō)明一下,大家看到,3個(gè)參數(shù)都是引用,而第一個(gè)是rNextPosition,顧名思義,在函數(shù)返回之后,它將會(huì)指像下一個(gè)元組,當(dāng)然這是在表還未遍歷完的時(shí)候,否則,它將被置為空(NULL)。
【】,利用下標(biāo)取元素的這個(gè)操作符,在CMap中被重載,用來(lái)返回指定Key值數(shù)據(jù)的引用,不過(guò)在注釋#3處,對(duì)于先取"4th"這個(gè)Point的引用然后賦值的用法,看起來(lái),似乎有點(diǎn)聰明過(guò)了頭,因?yàn)樵谶@之前,我們還沒(méi)有插入"4th"所對(duì)應(yīng)的元組,但是,程序卻能正常的運(yùn)行!為什么?其實(shí),這樣的用法是十分正確的,因?yàn)镃Map畢竟不是數(shù)組,它是沒(méi)有邊界的,當(dāng)CMap在獲得一個(gè)它無(wú)法查詢(xún)到的Key值的時(shí)候,它會(huì)將這個(gè)Key以及一個(gè)空的數(shù)據(jù)類(lèi)型追加到Hash表中去,從而保證了上面的程序可以無(wú)誤的運(yùn)行。
我們已經(jīng)說(shuō)過(guò),ARG_KEY是作為類(lèi)型參數(shù)傳入CMap的,但并不是任何類(lèi)型都可以作為ARG_KEY傳入的。為什么?看樣子,這次不得不簡(jiǎn)單的說(shuō)說(shuō)Hash表的散列函數(shù)了。每個(gè)Hash表,總會(huì)使用一些散列函數(shù),用來(lái)查找Key所對(duì)應(yīng)的Value,理想狀態(tài)下,我們當(dāng)然希望Hash表,就是一個(gè)數(shù)組,雖然這不可能,不過(guò)這樣理解,可以幫助我們更好的理解Hash表的物理結(jié)構(gòu),就讓我們暫時(shí)把它看成一個(gè)數(shù)組吧。數(shù)組總是使用下標(biāo)來(lái)直接獲取元素的存儲(chǔ)地址,而下標(biāo),顯然應(yīng)該是個(gè)非負(fù)整數(shù),從而Hash表,也應(yīng)該具備這樣的特性,至少必須存在某種算法可以使傳入的Key可以直接的轉(zhuǎn)化為一個(gè)非負(fù)的整數(shù),這也就是ARG_KEY的選擇標(biāo)準(zhǔn)。從而對(duì)象、引用無(wú)論如何都不應(yīng)該作為ARG_KEY成為CMap的類(lèi)型參數(shù),而int、unsigned int、指針以及地址就成為了ARG_KEY的常用類(lèi)型參數(shù),其實(shí)也就是那些類(lèi)似于整型的數(shù)據(jù)類(lèi)型。常常看到一些人在用CMap的時(shí)候,試圖使用CString作為CMap中ARG_KEY的類(lèi)型參數(shù),這是應(yīng)該被糾正的方向性錯(cuò)誤,但有些人似乎會(huì)理直氣壯的反駁我,因?yàn)樗麄儼l(fā)現(xiàn)類(lèi)型參數(shù)KEY是可以使用CString的,這很奇怪嗎?我說(shuō)過(guò)KEY不能使用CString嗎?之所以KEY可以使用CString而ARG_KEY卻用的是LPCTSTR,那是因?yàn)镃String重載了operator==(const char*)這個(gè)判等操作符,當(dāng)CMap從Hash表中獲得KEY之后,它會(huì)將ARG_KEY與KEY直接相比較。真正存于CMap內(nèi)部的是KEY,也就是CString。這也就是為什么,我們經(jīng)常會(huì)看到CMap被實(shí)化成CMap<CString, LPCTSTR/*相當(dāng)于const char*,非Unicode情況下*/, CString,CString&>這樣的一個(gè)四不像實(shí)化類(lèi)的原因,至于CMap的效率優(yōu)化問(wèn)題,我們會(huì)在以后的文章中繼續(xù)與大家探討。
CMap的確是個(gè)很不錯(cuò)的數(shù)據(jù)結(jié)構(gòu),尤其在你建立一個(gè)字典的時(shí)候。比如idealsoft的含義是"曳光科技",這就是一個(gè)元組,也就是一個(gè)Pair,Key是"idealsoft",而Value是"曳光科技"。
====================================================================
#include <afxwin.h>
#include <afxtempl.h>
void main()
{
AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0);
CMap <int, int, CString, CString> m_cMap;
m_cMap.SetAt(9923033, "張三 ");
m_cMap.SetAt(9826033, "張A ");
m_cMap.SetAt(9923063, "張B ");
m_cMap.SetAt(9923093, "張C ");
CString strName;
m_cMap.Lookup(9923063, strName);
AfxMessageBox(strName);
}
2011年8月26日
COLORMAP ColorMap[3] = {
{ RGB(128,128,128), ::GetSysColor(COLOR_BTNSHADOW) },
{ RGB(192,192,192), ::GetSysColor(COLOR_BTNFACE) },
{ RGB(255,255,255), ::GetSysColor(COLOR_BTNHILIGHT)}
};
CBitmap Bitmap;
Bitmap.LoadMappedBitmap(IDB_BITMAP, 0, ColorMap, 3);
BOOL LoadMappedBitmap(
UINT nIDBitmap, //位圖的標(biāo)識(shí)
UINT nFlags = 0, //通常情況下為0,當(dāng)將該位圖作
為屏蔽位圖使用時(shí)該參數(shù)為CMB_MASKED
LPCOLORMAP lpColorMap = NULL,
int nMapSize = 0);
【返回值】該成員函數(shù)調(diào)用成功返回一個(gè)非零值,否則返回零。
【參 數(shù)】
nIDBitmap
nFlags
通常情況下為0,當(dāng)將該位圖作為屏蔽位圖使用時(shí)該參數(shù)為CMB_MASKED。
lpColorMap
一個(gè)指向COLORMAP數(shù)據(jù)類(lèi)型數(shù)組的指針。COLORMAP的數(shù)據(jù)結(jié)構(gòu)如下:
typedef struct _COLORMAP{
COLORREF from; // 邏輯調(diào)色板的顏色
COLORREF to; // 物理調(diào)色板的顏色
}COLORMAP, FAR* LPCOLORMAP;
nMapSize
指定數(shù)組中數(shù)組元素的個(gè)數(shù)。
【注 釋】本成員函數(shù)可以將一個(gè)設(shè)備無(wú)關(guān)位圖裝入CBitmap類(lèi)的對(duì)象,并根據(jù)邏輯調(diào)色板與物理調(diào)色板的映射關(guān)系使系統(tǒng)正確地顯示該位圖。
_COLORMAP iColor[2]={{RGB(191,191,196),::GetSysColor(COLOR_3DFACE)},{RGB(192,192,192),::GetSysColor(COLOR_3DFACE)}};
m_bmToolbarHi.LoadMappedBitmap( IDB_TOOLBARHI,0,iColor,2);
m_wndToolBar.SetBitmap( (HBITMAP)m_bmToolbarHi );
這是我的代碼,可他不工作啊:~(
有個(gè)問(wèn)題提醒一下:
庫(kù)中的LoadMappedBitmap函數(shù)對(duì)超過(guò)256色的圖像好像無(wú)效,而且會(huì)死掉。
對(duì)不超過(guò)256色的圖像是有效的。
我知道了,我的圖像是256色的,這不錯(cuò)。但是轉(zhuǎn)換的顏色好像也算一種顏色。我把我導(dǎo)出的圖像色數(shù)改成128,結(jié)果就好了 :D