Visual C++編程技巧(下)

來源:互聯網
上載者:User
49、如何?一個橡皮區矩形

CRectTracker是一個很有用的類,可以通過調用CRectTracker:: TrackRubberBand響應WM_LBUTTONDOWN訊息來建立一個橡皮區矩形。下例表明使用CRectTracker移動和重設視窗中的藍色橢圓的大小是很容易的事情。

首先,在檔案檔中聲明一個CRectTracker資料成員:

class CSampleView : Public CView

{

public :

CrectTracker m_tracker;

};

其次,在文檔類的建構函式中初始化CRectTracker 對象:

CSampleDoc:: CSampleDOC ()

{

//Initialize tracker position, size and style.

m_tracker.m_rect.SetRect (0, 0, 10, 10);

m_tracker.m_nStyle=CRectTracker:: resizeInside |

CRectTracker:: dottedLine;

}

然後,在OnDraw函數中畫橢圓和蹤跡矩形:

void CSampleView:: OnDraw (CDC* pDC)

{

CSampleDoc* pDoc=GetDocument ();

ASSERT_VALID (pDoc);

//Select blue brush into device context.

CBrush brush (RGB (0, 0, 255));

CBrush* pOldBrush=pDC->SelectObject (&brush);

//draw ellipse in tracking rectangle.

Crect rcEllipse;

pDoc->m_tracker.GetTrueRect (rcEllipse);

pDC->Ellipse (rcEllipse);

//Draw tracking rectangle.

pDoc->m_tracker.Draw (pDC);

//Select blue brush out of device context.

pDC->Selectobject (pOldBrush);

}

最後,使用ClassWizard處理WM_LBUTTONDOWN訊息,並增加下述代碼。該段代碼根據滑鼠擊鍵情況可以拖放、移動或者重設橢圓的大小。

void CSampleView::OnLButtonDown (UINT nFlags, CPoint point)

{

//Get pointer to document.

CSampleDoc* pDoc=GetDocument ();

ASSERT_VALID (pDoc);

//If clicked on ellipse, drag or resize it. Otherwise create a

//rubber-band rectangle nd create a new ellipse.

BOOL bResult=pDoc->m_tracker.HitTest (point)!=

CRectTracker::hitNothing;

//Tracker rectangle changed so update views.

if (bResult)

{

pDoc->m_tracker.Track (this,point,TRue);

pDoc->SetModifiedFlag ();

pDoc->UpdateAllViews (NULL);

}

else

pDoc->m-tracker.TrackRubberBand (this,point,TRUE);

CView:: onLButtonDown (nFlags,point);

}

50、如何更新翻轉背景顏色的文本

調用CDC:: SetBkmode並傳送OPAQUE用當前的背景顏色填充背景,或者調用CDC::SetBkMode並傳送TRANSPAARENT使背景保持不變,這兩種方法都可以設定背景模式。下例設定背景模式為TRANSPARENT,可以兩次更新串,用花色帶黑陰影更新文本。黑色串在紅色串之後,但由於設定了背景模式仍然可見。

void CSampleView:: OnDraw (CDC* pDC)

{

//Determint size of view.

CRect rcView;

GetClientRect (rcVieew);

//Create sample string to display.

CString str (_T ("Awesome Shadow Text..."));

//Set the background mode to transparent.

pDC->SetBKMode (TRANSPARENT);

//Draw black shadow text.

rcView.OffsetRect (1, 1);

pDc->SetTextColor (RGB (0, 0, 0));

pDC->DrawText (str, str.GetLength (), rcView,

DT_SINGLELINE | DT_CENTER | DT_VCENTER);

//Draw red text.

rcView.OffsetRect (-1,-1);

pDc->SetTextColor (RGB (255, 0, 0));

pDC->DrawText (str, str.GetLength (), rcView,

DT_SINGLELINE | DT_CENTER | DT_VCENTER);

}

51、如何建立一個具有特定點大小的字型

可以指定字型邏輯單位的大小,但有時指定字型的點的大小可能會更方便一些。可以如下將字型的點轉換為字型的高度:

int nHeigth=mulDiv (nPointSize, -dc.GetDeviceCaps (LOGPIXELSY), 72);

下例建立了一個8點的Apial字型:

CClientDC dc (AqfxGetMainWnd ());

m_font. CreateFont (MulDiv (8, -dc.GetDeviceCaps (LOGPIXELSY),

72),0,0,0,FW_NORMAL,0,0,0,ANSI_CHARSET,

OUT_STROKE_PRECIS,CLIP_STROKE_PRECIS,DRAFT_QUALITY,

VARIABLE_PITCH | FF-SWISS,_T ("Arial"));

52、如何計算一個串的大小

函數CDC:: Det text Extent 根據當前選擇的字型計算一個串的高度和寬度。如果使用的不是系統字型而是其他字型,則在調用GetTextExtent之前將字型選進裝置上下文中是很重要的,否則計算高度和寬度時將依據系統字型,由此得出的結果當然是不正確的。下述樣板程式當改變下壓按鈕的標題時動態調整按鈕的大小,按鈕的大小由按鈕的字型和標題的大小而定。響應訊息WM_SETTEXT時調用OnSetText,該訊息使用ON_MESSAE巨集指令定義的使用者自訂訊息。

LRESULT CMyButton:: OnSettext (WPARAM wParam, LPARAM lParam)

{

//Pass message to window procedure.

LRESULT bResult=CallWindowProc (*GetSuperWndProcAddr (),

m_hWnd, GetCurrentMessage () ->message,wParam,lParam);

//Get title of push button.

CString strTitle;

GetWindowText (strTitle);

//Select current font into device context.

CDC* pDC=GetDc ();

CFont*pFont=GetFont ();

CFont*pOldFont=pDC->SelectObject (pFont);

//Calculate size of title.

CSize size=pDC->GetTextExent (strTitle,strTitle.GetLength ());

//Adjust the button's size based on its title.

//Add a 5-pixel border around the button.

SetWindowPos (NULL, 0, 0, size.cx+10, size.cy+10,

SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);

//Clean up.

pDC->SelectFont (pOldFont);

ReleaseDC (pDC);

return bResult;

}

53、如何顯示旋轉文本

只要使用者使用TrueType或者GDI筆或字型就可以顯示旋轉文本(有些硬體裝置也支援旋轉點陣字型)。LOGFONT結構中的ifEscapement成員指定了文本行和x軸的角度,角度的單位是十分之一度而不是度,例如,ifEscapement為450表示字型旋轉45度。為確保所有的字型沿座標系統的同一方向旋轉,一定要設定ifEscapement成員的CLIP_LH_ANGLES位,否則,有些字型可能反向旋轉。下例使用了14點Arial字型每間隔15度畫一個串。

void CSampleView:: OnDraw (CDC* pDC)

{

//Determine the size of the window.

CRect rcClient;

GetClientRect (rcClient);

//Create sample string.

CString str (_T ("Wheeee...I am rotating!"));

//Draw transparent, red text.

pDC->SetBkMode (TRANSPARENT);

pDC->SetTextColor (RGB (255,0,0));

CFont font; //font object

LOGFONT stFont; //font definition

//Set font attributes that will not change.

memset (&stFont, 0, sizeof (LOGFONT));

stFont.ifheight=MulDiv (14, -pDC->GetDeviceCaps (LOGPIXELSY), 72);

stFont.ifWeight=FW_NORMAL;

stFont.ifClipPrecision=LCIP_LH_ANGLES;

strcpy (stFont.lfFaceName, "Arial");

//Draw text at 15degree intervals.

for (int nAngle=0; nAngle<3600; nAngle+=150)

{

//Specify new angle.

stFont.lfEscapement=nAngle;

//Create and select font into dc.

font.CreateFontIndirect (&stfont);

CFont* pOldFont=pDC->SelectObject (&font);

//Draw the text.

pDC->SelectObject (pOldFont);

font.DelectObjext ();

}

}

54、如何正確顯示包含標籤字元的串

調用GDI文本繪畫函數時需要展開標籤字元,這可以通過調用CDC:: TabbedTextOut或者CDC:: DrawText並指定DT_EXPANDTABS標誌來完成。TabbedTextOut函數允許指定標籤位的數組,下例指定每20裝置單位展開一個標籤:

void CSampleView:: OnDraw (CDC* pDC)

{

CTestDoc* pDoc=GetDocument ();

ASSERT_VALID (pDoC);

CString str;

str.Format (_T ("Cathy/tNorman/tOliver"));

int nTabStop=20; //tabs are every 20 pixels

pDC->TabbedtextOut (10, 10, str, 1, &nTabStop, 10);

}

55、串太長時如何在其末尾顯示一個省略符號

調用CDC:: DrawText並指定DT_END_ELLIPSIS標誌,這樣就可以用小略號取代串末尾的字元使其適合於指定的邊界矩形。如果要顯示路徑資訊,指定DT_END_ELLIPSIS標誌並省略符號取代串中間的字元。

void CSampleView:: OnDraw (CDC* pDC)

{

CTestDoc* pDoc=GetDocument ();

ASSERT_VALID (pDoc);

//Add ellpsis to end of string if it does not fit

pDC->Drawtext (CString ("This is a long string"),

CRect (10, 10, 80, 30), DT_LEFT | DT_END_ELLIPSIS);

//Add ellpsis to middle of string if it does not fit

pDC->DrawText (AfxgetApp () ->m_pszhelpfilePath,

CRect (10, 40, 200, 60), DT_LEFT | DT_PATH_ELLIPSIS);

}

56、如何快速地格式化一個CString對象

調用CString:: Format,該函數和printf函數具有相同的參數,下例說明了如何使用Format函數:

//Get size of window.

CRect rcWindow;

GetWindowRect (rcWindow);

//Format message string.

CString strMessage;

strMessage.Format (_T ("Window Size (%d, %d)"),

rcWindow.Width (), rcWindow.Height ());

//Display the message.

MessageBox (strmessage);

57、為什麼即使調用EnableMenuItem功能表項目後,功能表項目還處于禁止狀態

需要將CFrameWnd:: m_bAutomenuEnable設定為FALSE,如果該資料成員為TRUE(預設值),工作框將自動地禁止沒有ON_UPDATE_COMMAND_UI或者ON_COMMAND的功能表項目。

//Disable MFC from automatically disabling menu items.

m_bAuoMenuEnable=FALSE;

//Now enable the menu item.

CMenu* pMenu=GetMenu ();

ASSERT_VALID (pMenu);

pMenu->EnableMenuItem (ID_MENU_ITEM,MF_BYCOMMAND | MF_ENABLED);

58、如何給系統功能表添加一個功能表項目

給系統功能表添加一個功能表項目需要進行下述三個步驟:

首先,使用Resource Symbols對話(在View菜單中選擇Resource Symbols...

可以顯示該對話)定義功能表項目ID,該ID應大於0x0F而小於0xF000;

其次,調用CWnd::GetSystemMenu擷取系統功能表的指標並調用CWnd:: Appendmenu將功能表項目添加到菜單中。下例給系統功能表添加兩個新的功能表項目:

int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct)

{

//Make sure system menu item is in the right range.

ASSERT (IDM_MYSYSITEM &0xFFF0)==IDM_MYSYSITEM);

ASSERT (IDM-MYSYSITEM<0xF000);

//Get pointer to system menu.

CMenu* pSysmenu=GetSystemmenu (FALSE);

ASSERT_VALID (pSysMenu);

//Add a separator and our menu item to system menu.

CString StrMenuItem (_T ("New menu item"));

pSysMenu->Appendmenu (MF_SEPARATOR);

pSysMenu->AppendMenu (MF_STRING, IDM_MYSYSITEM, strMenuitem);

}

現在,選擇系統功能表項時使用者應進行檢測。使用ClassWizard處理

WM_SYSCOMMAND訊息並檢測使用者菜單的nID參數:

void CMainFrame:: OnSysCommand (UINT nID,LPARAM lParam)

{

//Determine if our system menu item was selected.

if ( (nID & 0xFFF0)==IDM_MYSYSITEM)

{

//TODO-process system menu item

}

else

CMDIFrameWnd:: OnSysCommand (nID, lParam);

}

最後,一個設計良好的UI應用程式應當在系統功能表項加亮時在狀態條顯示一個協助資訊,這可以通過增加一個包含系統功能表基ID的串表的入口來實現。

59、如何確定頂層菜單所佔據的菜單行數

這可以通過簡單的減法和除法來實現。首先,使用者需要計算主框視窗的高度和客戶區;其次,從主框視窗的高度中減去客戶區、框邊界以及標題的高度;最後,除以功能表列的高度。下例成員函數是一個計算主框菜單所佔據的行數的代碼實現。

int CMainFrame:: GetMenuRows ()

{

CRect rcFrame,rcClient;

GetWindowRect (rcFrame);

GetClientRect (rcClient);

return (rcFrame.Height () -rcClient.Height ()-

:: GetSystemMetrics (SM_CYCAPTION) -

(:: getSystemMetrics (SM_CYFRAME) *2)) /

:: GetSystemMetrics (SM_CYMENU);

}

60、在使用者環境中如何確定系統顯示元素的顏色

調用SDK函數GetSysColor可以擷取一個特定顯示元素的顏色。下例說明了如何在MFC函數CMainFrameWnd:: OnNcPaint中調用該函數設定視窗標題顏色。

void CMiniFrameWnd:: OnNcPaint ()

{

dc.SetTextColor (:: GetSysColor (m_bActive ?

COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT));

}

61、如何查詢和設定系統參數

在Windows 3.1 SDK中介紹過SDK函數SystemParametersInfo,調用該函數可以查詢和設定系統參數,諸如按鍵的重複速度設定、滑鼠雙擊延遲時間、表徵圖字型以及案頭覆蓋位元影像等等。

//Create a font that is used for icon titles.

LOGFONT stFont;

:: SystemParametersInfo (SPIF_GETICONTITLELOGFONT,

sizeof (LOGFONT), &stFont, SPIF_SENDWININICHANGE);

m_font.CreateFontIndirect (&stFont);

//Change the wallpaper to leaves.bmp.

:: SystemParametersInfo (SPI_SETDESKWALLPAPER, 0,

_T (" forest.bmp"), SPIF_UPDATEINIFILE);

62、如何使用一個預定義的Windows游標

調用CWinApp:: LoadStandardCursor並傳送游標標識符。

BOOL CSampleDialog:: OnSetCursor (CWnd* pWnd, UINT nHitTest, UINT message)

{

//Display wait cursor if busy.

if (m_bBusy)

{

SetCursor (AfxGetApp () ->LoadStandardCursor (IDC_WAIT));

return TRUE;

}

return CDialog:: OnSetCursor (pWnd. nHitTest,message);

}

63、如何確定當前螢幕解析度

調用SDK函數GetSystemMetrics,該函數可以檢索有關windows顯示資訊,諸如標題大小、邊界大小以及捲軸大小等等。

//Initialize CSize object with screen size.

CSize sizeScreen (GetSystemMetrics (SM_CXSCREEN),

GetSystemMetrics (SM_CYSCREEN));

64、如何檢索原先的Task Manager應用程式使用的工作清單

原先的Task Manager應用程式顯示頂層視窗的列表。為了顯示該列表,視窗

必須可見、包含一個標題以及不能被其他視窗擁有。調用CWnd:: GetWindow可以

檢索頂層視窗的列表,調用IsWindowVisible、GetWindowTextLength以及GetOwner

可以確定視窗是否應該在列表中。下例將把TaskManager視窗的標題填充到列表中。

void GetTadkList (CListBox&list)

{

CString strCaption; //Caption of window.

list.ResetContent (); //Clear list box.

//Get first Window in window list.

ASSERT_VALID (AfxGetMainWnd ());

CWnd* pWnd=AfxGetMainWnd () ->GetWindow (GW_HWNDFIRST);

//Walk window list.

while (pWnd)

{

// I window visible, has a caption, and does not have an owner?

if (pWnd ->IsWindowVisible () &&

pWnd ->GetWindowTextLength () &&! pWnd ->GetOwner ())

{

//Add caption o window to list box.

pWnd ->GetWindowText (strCaption);

list.AddString (strCaption);

}

//Get next window in window list.

pWnd=pWnd->GetWindow (GW_HWNDNEXT);

}

}

65、如何確定Windows和Windows系統目錄

有兩個SDK函數可以完成該功能。GetWindowsDirectory和GetSystemDirectory,下例說明了如何使用這兩個函數:

TCHAR szDir [MAX_PATH];

//Get the full path of the windows directory.

:: GetWindowsDirectory (szDir, MAX_PATH);

TRACE ("Windows directory %s/n", szDir);

//Get the full path of the windows system directory.

:: GetSystemDirectory (szDir, MAX_PATH);

TRACE ("Windows system directory %s/n", szDir);

66、在哪兒建立臨檔案

調用SDK函數GetTemPath可以確定臨時檔案的目錄,該函數首先為臨時路徑檢測TMP環境變數:如果沒有指定TMP,檢測TMP環境變數,然後返回到目前的目錄。下例說明了如何建立一個臨時檔案。

//get unique temporary file.

CString strFile;

GetUniqueTempName (strFile);

TRY

{

//Create file and write data.Note that file is closed

//in the destructor of the CFile object.

CFile file (strFile,CFile:: modeCreate | CFile:: modeWrite);

//write data

}

CATCH (CFileException, e)

{

//error opening file

}

END_CATCH

Void GetuniqueTempName (CString& strTempName)

{

//Get the temporary files directory.

TCHAR szTempPath [MAX_PATH];

DWORD dwResult=:: GetTempPath (MAX_PATH, szTempPath);

ASSERT (dwResult);

//Create a unique temporary file.

TCHAR szTempFile [MAX_PATH];

UINT nResult=GetTempFileName (szTempPath, _T ("~ex"),0,szTempfile);

ASSERT (nResult);

strTempName=szTempFile;

}

67、如何訪問桌面視窗

靜態函數CWnd:: GetDesktopWindow 返回桌面視窗的指標。下例說明了MFC函數CFrameWnd::BeginModalStae是如何使用該函數進入內部視窗列表的。

void CFrameWnd::BeginModalState ()

{

//first count all windows that need to be disabled

UINT nCount=0;

HWND hWnd=:: GetWindow (:: GetDesktopWindow (), GW_CHILD);

while (hWnd!=NULL)

{

if (:: IsWindowEnabled (hwnd) &&

CWnd::FromHandlePermanent (hWnd)!=NULL &&

AfxIsDescendant (pParent->m_hWnd, hWnd) &&

:: SendMessage (hWnd, WM_DISABLEMODAL, 0, 0)==0)

{

++nCount;

}

hWnd=:: GetWindow (hWnd, GW_HWNDNEXT);

}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.