现在的位置: 首页 > 综合 > 正文

window 编程指南(二)

2013年09月16日 ⁄ 综合 ⁄ 共 9581字 ⁄ 字号 评论关闭

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);
     }
     …
}
 
68、
    12. 如何让窗口和 MDI窗口一启动就最大化和最小化?
     该条两条合并为一条了.
  

抱歉!评论已关闭.