首页 > C/C++开发工具专区 > VC技术 > VC++若干编程技巧
2006
02-23

VC++若干编程技巧

 Visual C++是一种面向对象的可视化编程工具,由于生成的应用程序框架使程序的用户界面和程序结构都只能具有标准形式,而在实际的程序设计中,常常需要设计一些非标准的应用程序,或实现一些特别的功能或操作,因此可以使用一些技巧来修改应用程序框架,以得到所需的应用效果。


  一、修改主窗口风格


  AppWizard生成的应用程序框架的主窗口具有缺省的窗口风格,比如在窗口标题条中自动添加文档名、窗口是叠加型的、可改变窗口大小等。要修改窗口的缺省风格,需要重载CWnd::PreCreateWindow(CREATESTRUCT &cs)函数,并在其中修改CREATESTRUCT型参数cs。


  CWnd::PreCreateWindow函数先于窗口创建函数执行。如果该函数被重载,则窗口创建函数将使用CWnd::PreCreateWindow函数返回的CREATESTRUCTcs参数所定义的窗口风格来创建窗口;否则使用预定义的窗口风格。


  CREATESTRUCT结构定义了创建函数创建窗口所用的初始参数,其定义如下:



typedef struct tagCREATESTRUCT {


LPVOID lpCreateParams; //创建窗口的基本参数


HANDLE hInstance;


//拥有将创建的窗口的模块实例句柄


HMENU hMenu; //新窗口的菜单句柄


HWND hwndParent; //新窗口的父窗口句柄


int cy; //新窗口的高度


int cx; //新窗口的宽度


int y; //新窗口的左上角Y坐标


int x; //新窗口的左上角X坐标


LONG style; //新窗口的风格


LPCSTR lpszName; //新窗口的名称


LPCSTR lpszClass; //新窗口的窗口类名


DWORD dwExStyle; //新窗口的扩展参数


} CREATESTRUCT;


下例中的代码将主框窗口的大小


固定为1/4屏幕,标题条中仅显示窗口名,


不显示文档名。


BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)


{


// TODO: Modify the Window class


or styles here by modifying


// the CREATESTRUCT cs


 


//修改主窗风格


cs.style&=~FWS_ADDTOTITLE; //去除标题条中的文档名


cs.style&=~WS_THICKFRAME; //去除可改变大小的边框


cs.style |= WS_DLGFRAME; //增加不能改变大小的边框


 


//确定主窗的大小和初始位置


int cxScreen = ::GetSystemMetrics(SM_CXSCREEN);


//获得屏幕宽


int cyScreen = ::GetSystemMetrics(SM_CYSCREEN);


//获得屏幕高


cs.x = 0; //主窗位于左上角


cs.y = 0;


cs.cx = cxScreen/2; //主窗宽为1/2屏幕宽


cs.cy = cxScreen/2; //主窗高为1/2屏幕高



return CMDIFrameWnd::PreCreateWindow(cs);


}


  二、创建不规则形状窗口


  标准的Windows窗口是矩形的,但在有些时候我们需要非矩形的窗口,比如圆形的、甚至是不规则的。借助CWnd类的SetWindowRgn函数可以创建不规则形状窗口。
CWnd::SetWindowRgn的函数原型如下:


int SetWindowRgn( HRGN hRgn, //窗口区域句柄


BOOL bRedraw ); //是否重画窗口


  创建非矩形窗口的方法如下:首先,在窗口类中定义区域类成员数据(如CRgnm_rgnWnd);其次,在窗口的OnCreate函数或对话框的OnInitDialog函数中调用CRgn类的CreateRectRgn、CreateEllipticRgn或CreatePolygonRgn函数创建所需的区域,并调用SetWindowRgn函数。


  下例将生成一个椭圆窗口。


  1.在Developer Studio中选取File菜单中的New命令,在出现的New对话框中选择创建MFCAppWizard(exe)框架应用程序,并输入项目名为EllipseWnd。设定应用程序类型为基于对话框(Dialog based),其它选项按缺省值创建项目源文件。
  2.使用资源编辑器从主对话框(ID为IDD_ELLIPSEWND_DIALOG)删除其中的所有控制,并从其属性对话框(Dialog Properties)中设定其风格为Popup、无标题条和边框。
  3.在EllipseWndDlg.h源文件中给主对话框类CEllipseWndDlg增加一个CRgn类保护型数据成员m_rgnWnd,它将定义窗口的区域。
  4.在EllipseWndDlg.cpp源文件中修改主对话框类CEllipseWndDlg的OnInitDialog()函数,增加m_rgnWnd的创建,并将其定义为窗口区域。粗体语句为新增部分。


BOOL CEllipseWndDlg::OnInitDialog()


{


CDialog::OnInitDialog();


// Add “About…” menu item to system menu.


// IDM_ABOUTBOX must be in the system command range.


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


ASSERT(IDM_ABOUTBOX < 0xF000);


CMenu* pSysMenu = GetSystemMenu(FALSE);


if (pSysMenu != NULL)


{


CString strAboutMenu;


strAboutMenu.LoadString(IDS_ABOUTBOX);


if (!strAboutMenu.IsEmpty())


{


pSysMenu->AppendMenu(MF_SEPARATOR);


pSysMenu->AppendMenu


(MF_STRING, IDM_ABOUTBOX, strAboutMenu);


}


}


// Set the icon for this dialog.


The framework does this automatically


// when the application’s main window is not a dialog


SetIcon(m_hIcon, TRUE);


// Set big icon


SetIcon(m_hIcon, FALSE);


// Set small icon


//设置窗口标题为”椭圆窗口”,


虽然对话框没有标题条,


//但在任务条的按钮中仍需要标题


SetWindowText(_T(“椭圆窗口”));


//取得屏幕宽、高


int cxScreen = ::GetSystemMetrics(SM_CXSCREEN);


int cyScreen = ::GetSystemMetrics(SM_CYSCREEN);


//设置椭圆X、Y方向的半径


int nEllipseWidth = cxScreen/8;


int nEllipseHeight = cyScreen/8;


//将窗口大小设为宽nEllipseWidth,


高nEllipseHeight


//并移至左上角


MoveWindow(0, 0, nEllipseWidth, nEllipseHeight);


//创建椭圆区域m_rgnWnd


m_rgnWnd.CreateEllipticRgn(0, 0,


nEllipseWidth, nEllipseHeight);


// 将m_rgnWnd设置为窗口区域


SetWindowRgn((HRGN)m_rgnWnd, TRUE);


return TRUE; // return TRUE unless


you set the focus to a control


}


  三、显示旋转文本


  在有的应用中,为了达到特殊的效果,经常需要显示旋转的文本。文本的显示方式,包括旋转,都是由字体来设置的。


  字体的属性主要由创建字体时使用的LOGFONT结构规定,该结构中的lfEscapement域指定了文本行与X轴(水平轴)的角度,其角度单位是十分之一度。为了使所有的字体向相同的方向旋转,还应同时将LOGFONT结构的lfClipPrecision域设为CLIP_LH_ANGLES。


  下面的代码将在对话框中显示在同一起点每隔15度显示一行文本:
void CRotateTextDlg::OnPaint()


{


CPaintDC dc(this); // device context for painting


if (IsIconic())


{


SendMessage(WM_ICONERASEBKGND,


(WPARAM) dc.GetSafeHdc(), 0);


// Center icon in client rectangle


int cxIcon = GetSystemMetrics(SM_CXICON);


int cyIcon = GetSystemMetrics(SM_CYICON);


CRect rect;


GetClientRect(&rect);


int x = (rect.Width()- cxIcon+ 1) / 2;


int y = (rect.Height()- cyIcon+ 1) / 2;


// Draw the icon


dc.DrawIcon(x, y, m_hIcon);


}


else


{


CRect rc;


GetClientRect(rc);


CString str(_T(“…………旋转文本!”));


dc.SetBkMode(TRANSPARENT);


dc.SetTextColor(RGB(0,0,255));


CFont font;


LOGFONT lf;


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


lf.lfHeight =-14;


lf.lfWeight = FW_NORMAL;


lf.lfClipPrecision = CLIP_LH_ANGLES;


strcpy(lf.lfFaceName, “宋体”);


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


{


lf.lfEscapement = i;


font.CreateFontIndirect(&lf);


CFont*pOldFont = dc.SelectObject(&font);


dc.TextOut(rc.right/2, rc.bottom/2,str);


dc.SelectObject(pOldFont);


font.DeleteObject();


}


CDialog::OnPaint();


}


} 


留下一个回复