小弟在本機上先安裝了virtual box,並自動產生了virtual box所需的網路橋接裝置-->VirtualBox Host-Only Network,
其後又安裝了另外一套VMware workstation,並在VMware下建立了Guest OS(Fedora),
在GuestOS的Network Connection當中,設置為Bridged,以便於網路上的其他主機能直接存取Fedora,
Fedora的network settingk則是使用static ip的方式,
剛開始使用一切都正常,直到有天關機後再開啟,才發現Fedora無法對外連線,
但是VMware底下的其他Guest OS 只要是使用NAT的方式都能正常連線,唯獨bridge有問題,
查了一下才發現原理是這樣的--->
VMware安裝完後,會生成三個網路橋接裝置,分別為VMnet0,VMnet1,VMnet8(詳細請自己搜尋),
其中Bridged模式走的是VMnet0,此橋接裝置會將Guest OS的網卡導到Host實體機器的網卡上,
但是若實體機器有多張網卡時,則會依照設定值決定導到哪一張實體網卡上,
設定值有兩種:Automatic or 某一張實體網卡,
我在VMware安裝完後從未進來設定過,其預設值為Automatic,
But!!!VMware 將 VirtualBox Host-Only Network 也當作是實體網卡!!!
所以導致Fedora or Guest OS 不管怎麼修改設定,都無法連到真正的實體網路~~~><~~~
所以,解決方法就是
1.進入VMware Network Editor->點選VMnet0-->下方WMnet Information-->在Bridged to的下拉式選單中選擇一張實體網卡!
或是
2.右方的 Automatic Settings內,將VirtualBox Host-Only Ethernet Adapter的勾選取消,Bridged to的下拉選單仍維持
"Automatic"
搞定,收工!
ref:
VMWare虛擬機Bridged類型網卡ping不通的原因和解決辦法
2013/12/20
2013/11/21
[MFC] TreeCtrl使用問題
前提:TreeCtrl需帶有 "Check Boxes"屬性
問題一:
OnInitDialog時,在treectrl內新增item後,需要將此項目的checkbox勾選,但是SetCheck卻無效?
回答一:
若要在初始化時期就設定treectrl's check box狀態,且在UI上表現出來,需在設定check box前,重新設定一次tree ctrl屬性!
若是在OnInitDialog以後的function內設定treectrl's check box,則無此問題。
問題二:
當勾選/取消溝選Tree上任一Item後,要如何自動選擇目前的Item,而非總是選擇第一個Item?
回答二:
需要在Click事件動手腳!
方法1:
方法2:
方法1知道原理的朋友,歡迎留言解釋一下,感恩!
問題一:
OnInitDialog時,在treectrl內新增item後,需要將此項目的checkbox勾選,但是SetCheck卻無效?
回答一:
若要在初始化時期就設定treectrl's check box狀態,且在UI上表現出來,需在設定check box前,重新設定一次tree ctrl屬性!
若是在OnInitDialog以後的function內設定treectrl's check box,則無此問題。
BOOL TestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//TODO:
mTreectrl.ModifyStyle( TVS_CHECKBOXES, 0 );
mTreectrl.ModifyStyle( 0, TVS_CHECKBOXES );
//在這之後新增的item就可以設定check box為有勾選狀態
HTREEITEM hCurItem = mTreectrl.InsertItem("Test");
mTreectrl.SetCheck(hCurItem,true);
}
問題二:
當勾選/取消溝選Tree上任一Item後,要如何自動選擇目前的Item,而非總是選擇第一個Item?
回答二:
需要在Click事件動手腳!
方法1:
void TestDlg::OnNMClickTree(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: 在此加入控制項告知處理常式程式碼
*pResult = 0;
//不正當寫法
//copy from OnTvnSelchangedTree
LPNMTREEVIEW pNMTreeView = reinterpret_cast(pNMHDR);
// pNMTreeView->ptDrag; //此point無法直接換算取得目前點擊的Item
CPoint pt;
pt.x = pNMTreeView->ptDrag.y; // 此point位置無法理解.
pt.y = pNMTreeView->itemNew.lParam; // 此point位置無法理解.
HTREEITEM hCurItem = mTreectrl.HitTest(pt);
if(hCurItem == NULL)
return;
//CString szText = mTreectrl.GetItemText(hCurItem);//驗證用,非必須.
mTreectrl.SelectItem(hCurItem);
}
方法2:
void TestDlg::OnNMClickTree(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: 在此加入控制項告知處理常式程式碼
*pResult = 0;
//正常寫法
CPoint pt;
GetCursorPos(&pt);
mTreectrl.ScreenToClient(&pt);
HTREEITEM hCurItem = mTreectrl.HitTest(pt);
if(hCurItem == NULL)
return;
//CString szText = mTreectrl.GetItemText(hCurItem);//驗證用,非必須.
mTreectrl.SelectItem(hCurItem);
}
方法1知道原理的朋友,歡迎留言解釋一下,感恩!
2013/08/29
[VC]GDI+繪圖
上次寫了一個GDI+做漸層效果,今天要再用就忘了一些步驟,所以把整個流程寫上來。
Step1.在stdafx.h中加入GDI+的Header file
Step2.在CWinApp中加入成員變數
Step3.至此,你的程式即可開始使用GDI+囉~
Step4.程式結束前,需釋放GDI+資源,請在CWinApp::ExitInstance()中加入:
以小弟需求來說--->漸層<---以下程式碼請參考:
ref:CodeProject_GDI+
ref:MSDN_GDI+
Step1.在stdafx.h中加入GDI+的Header file
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib, "gdiplus.lib")
Step2.在CWinApp中加入成員變數
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
在CWinApp::InitInstance()中初始化GDI+資源
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
Step3.至此,你的程式即可開始使用GDI+囉~
Step4.程式結束前,需釋放GDI+資源,請在CWinApp::ExitInstance()中加入:
GdiplusShutdown(gdiplusToken);
以小弟需求來說--->漸層<---以下程式碼請參考:
/*****MyClass.h*****/
class CMyClass:public CWnd
{
DECLARE_DYNAMIC(CMyClass)
public:
CMyClass();
virtual ~CMyClass();
protected:
afx_msg void OnPaint();
private:
Gdiplus::PointF m_gdiPoint1,m_gdiPoint2;
Gdiplus::Color m_gdiColor1,m_gdiColor2;
};
/*****MyClass.cpp*****/
CMyClass::CMyClass()
{
vm_gdiPoint1 =PointF(0,0);
vm_gdiPoint2 =PointF(0,18);
vm_gdiColor1 =Color(255,255,255);
vm_gdiColor2 =Color(0,0,0);
}
void CMyClass::OnPaint()
{
CPaintDC dc(this);
CRect rcBar;
GetClientRect(&rcBar);
//GDI+
Gdiplus::LinearGradientBrush gdiBrush(m_gdiPoint1,m_gdiPoint2,m_gdiColor1,m_gdiColor2);
Gdiplus::RectF gdiRc((Gdiplus::REAL)rcBar.left,(Gdiplus::REAL)rcBar.top, (Gdiplus::REAL)rcBar.Width(),(Gdiplus::REAL)rcBar.Height());
Graphics grThis(dc.m_hDC);
grThis.FillRectangle( &gdiBrush, gdiRc);
}
ref:CodeProject_GDI+
ref:MSDN_GDI+
2013/08/06
[VC] UNICODE 下的字串
從前寫好的ANSI CODE,在要編譯成UNICODE時,常會遇到字元bytes數問題,
往往都需在字串前強制加上L轉型成wchar;不過L到底是啥意思咧?
以下簡單介紹:
1. L"string"
表示將 ANSI字串轉換成unicode字串,就是每個英數字佔用兩個byte。
2. _T("string")
根據你的環境設置,編譯器會根據編譯目標環境選擇合適的(Unicode還是ANSI)字符處理方式。
如果你定義了UNICODE,那麼_T會把字符串前面加一個L。即此時的 _T("ABCD") 等同於 L"ABCD"。
如果沒有定義 UNICODE,那麼_T不會在字符串前面加那個L,_T("ABCD") 就等價於 "ABCD"
3. TEXT("str")、_TEXT("str")、_T("str")
這三個MACRO都是一樣的意思,即交由編譯器自動判斷。
如下面三語句:
TCHAR szStr1[] = TEXT("str1");
char szStr2[] = "str2";
WCHAR szStr3[] = L("str3");
當環境設置為UNICODE時,szStr1與str3所佔bytes數相等,
當環境未設置為UNICODE時,szStr1與str2所佔bytes數相等,
無論環境是否設置UNICODE,
str2永遠生成ANSI字串
str3永遠生成UNICODE字串
引用結論:為了程序的可移植性,建議盡量使用_T()表示字串。
ref. http://www.cnblogs.com/txwsh1/archive/2008/03/06/1093335.html
往往都需在字串前強制加上L轉型成wchar;不過L到底是啥意思咧?
以下簡單介紹:
1. L"string"
表示將 ANSI字串轉換成unicode字串,就是每個英數字佔用兩個byte。
2. _T("string")
根據你的環境設置,編譯器會根據編譯目標環境選擇合適的(Unicode還是ANSI)字符處理方式。
如果你定義了UNICODE,那麼_T會把字符串前面加一個L。即此時的 _T("ABCD") 等同於 L"ABCD"。
如果沒有定義 UNICODE,那麼_T不會在字符串前面加那個L,_T("ABCD") 就等價於 "ABCD"
3. TEXT("str")、_TEXT("str")、_T("str")
這三個MACRO都是一樣的意思,即交由編譯器自動判斷。
如下面三語句:
TCHAR szStr1[] = TEXT("str1");
char szStr2[] = "str2";
WCHAR szStr3[] = L("str3");
當環境設置為UNICODE時,szStr1與str3所佔bytes數相等,
當環境未設置為UNICODE時,szStr1與str2所佔bytes數相等,
無論環境是否設置UNICODE,
str2永遠生成ANSI字串
str3永遠生成UNICODE字串
引用結論:為了程序的可移植性,建議盡量使用_T()表示字串。
ref. http://www.cnblogs.com/txwsh1/archive/2008/03/06/1093335.html
2013/07/08
[MFC]CButton類如何響應WM_LBUTTONDOWN or WM_LBUTTONUP
建立一個button在dialog上的時候,他預設只有兩種事件可以響應,一是BN_CLICKED,另一則是BN_DOUBLECLICKED,那我要滑鼠左鍵按下與彈上的事件該怎麼做呢?
VC6是這樣做的:
1.在原Dialog下新增一CMyButton類別,其父類別為CButton。
2.為MyButton類別添加WM_LBUTTONDOWN與WM_LBUTTONUP的消息響應。
3.在Dialog下宣告一個MyButton的成員變數。
4.在MyButton.cpp->CMyButton::OnLButtonDown 內編輯你要滑鼠左鍵按下時,要做什麼事。
VC6是這樣做的:
1.在原Dialog下新增一CMyButton類別,其父類別為CButton。
2.為MyButton類別添加WM_LBUTTONDOWN與WM_LBUTTONUP的消息響應。
3.在Dialog下宣告一個MyButton的成員變數。
4.在MyButton.cpp->CMyButton::OnLButtonDown 內編輯你要滑鼠左鍵按下時,要做什麼事。
2013/07/04
[MFC] Tree Control Item 如何辨識唯一值
當我們在TreeCtrl上新增Item完後,若要在之後的操作中,判別此Item是否為唯一項目,目前只知道能用ItemText來判斷,但萬一ItemText非唯一值時,這樣的判斷方式就會有問題!
為了避免這樣的狀況發生,我在新增Item時,偷用一個欄位:lParam
先在.h定義一個與Item相關的其他訊息結構:
然後在.cpp內修改tree insert的部份:
當滑鼠拖曳某項Item時,會響應TVN_BEGINDRAG消息,這時從響應函式內將ID取出。
ps.方法1&2選一個用即可。
參考:StackOverflow how to create new Property for MFC(VC++) treeview Control?
為了避免這樣的狀況發生,我在新增Item時,偷用一個欄位:lParam
先在.h定義一個與Item相關的其他訊息結構:
typedef struct _treeItemInfo;
{
long nId;
//也可以放入其他需要紀錄的資訊,如 char sTextEx[8];
} ITEMINFO, *PITEMINFO;
然後在.cpp內修改tree insert的部份:
void CMyDlg::InsertNewItem()
{
HTREEITEM hSubItem;//新增Item後會回傳Item handle
TV_INSERTSTRUCT tvis;
TV_ITEM tvi;//set item member data
tvi.mask= TVIF_TEXT;
tvi.pszText= "test";//顯示在Item上的文字
//set insert struct;
member data
tvis.item= tvi;//insert items into CTreeCtrl
tvis.hParent= NULL;//此為根結點,故父節點為NULL
tvis.hInsertAfter= TVI_ROOT;//此為根結點
hSubItem = m_tree.InsertItem(tvis);
//方法1
PITEMINFO l_pItemEx = new ITEMINFO;
l_pItemEx->nId = 1000;
strcpy(l_pItemEx->sTextEx,"MyInfo");
m_tree.SetItemData( hSubItem, l_pItemEx);//將序號結構地址與此節點綁在一起
//方法2
DWORD dItemId = 1000;//表示Item序號
m_tree.SetItemData( hSubItem, dItemId);//將序號與此節點綁在一起
}
當滑鼠拖曳某項Item時,會響應TVN_BEGINDRAG消息,這時從響應函式內將ID取出。
void CMyDlg::OnTvnBegindrag(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast LPNMTREEVIEW(pNMHDR);
*pResult = 0;
// TODO: 在此加入控制項告知處理常式程式碼
DWORD tmpId;
//方法1
HTREEITEM hDragItem = ((NM_TREEVIEW*)pNMHDR)->itemNew.hItem;
PITEMINFO l_pTmpItemEx = (PITEMINFO)m_tree.GetItemData(hDragItem);
tmpId = m_tree.GetItemData(hDragItem);
}
//方法2
TVITEM tvitem= ((NM_TREEVIEW*)pNMHDR)->itemNew;
tmpId = tvitem.lParam;
//取得ID後,作你想做的事吧!
ps.方法1&2選一個用即可。
參考:StackOverflow how to create new Property for MFC(VC++) treeview Control?
[MFC]多消息響應同一函式
以前的寫法都是 one message mapping one function,
但有時候其實多個消息要做的事情,都會對到同一個對象,只是做的動作不同,
例如對同一個表單做新增、刪除、修改、查詢這樣的狀況,
這時候就可以用 ON_COMMAND_RANGE囉~
舊做法:
//m_tree的add del modify只是示意,並非真的有此member function,詳見msdn CTreeCtrl
本篇參考:msdn ON_MESSAGE_RANGE
但有時候其實多個消息要做的事情,都會對到同一個對象,只是做的動作不同,
例如對同一個表單做新增、刪除、修改、查詢這樣的狀況,
這時候就可以用 ON_COMMAND_RANGE囉~
舊做法:
ON_COMMAND(ID_TREEITEM_ADD, &CMyDialog::OnTreeItemAdd)
ON_COMMAND(ID_TREEITEM_DEL, &CMyDialog::OnTreeItemDel)
ON_COMMAND(ID_TREEITEM_MODIFY, &CMyDialog::OnTreeItemModify)
void CMyDialog::OnTreeItemAdd()
{
m_tree.add(hItem);
}
void CMyDialog::OnTreeItemDel()
{
m_tree.delete(hItem);
}
void CMyDialog::OnTreeItemModify()
{
m_tree.Modify(hItem);
}
改為:
ON_COMMAND_RANGE(ID_TREEITEM_ADD,ID_TREEITEM_MODIFY, &CMyDialog::OnTreeItem)
//此作法需注意:ID_TREEITEM_ADD、ID_TREEITEM_DEL、ID_TREEITEM_MODIFY在resource.h中必須為連續數,如1、2、3。
void CMyDialog::OnTreeItem(UINT nID)
{
switch(nID)
{
case ID_TREEITEM_ADD:
m_tree.add(hItem);
break;
case ID_TREEITEM_DEL:
m_tree.del(hItem);
break;
case ID_TREEITEM_MODIFY:
m_tree.Modify(hItem);
break;
default:
break;
}
}
//m_tree的add del modify只是示意,並非真的有此member function,詳見msdn CTreeCtrl
本篇參考:msdn ON_MESSAGE_RANGE
訂閱:
文章 (Atom)