VC开发小技巧


 
一、打开 CD-ROM

mciSendString("Set cdAudio door open wait",NULL,0,NULL);

二、关闭 CD_ROM

mciSendString("Set cdAudio door closed wait",NULL,0,NULL);

三、关闭计算机

OSVERSIONINFO OsVersionInfo; //
包含操作系统版本信息的数据结构
OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&OsVersionInfo); //
获取操作系统版本信息
if(OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
    //Windows98,
调用ExitWindowsEx()函数重新启动计算机
    DWORD dwReserved;
    ExitWindowsEx(EWX_REBOOT,dwReserved); //
可以改变第一个参数,实现注销用户、
    //
关机、关闭电源等操作
    //
退出前的一些处理程序
}

四、重启计算机

typedef int (CALLBACK *SHUTDOWNDLG)(int); //
显示关机对话框函数的指针
HINSTANCE hInst = LoadLibrary("shell32.dll"); //
装入shell32.dll
SHUTDOWNDLG ShutDownDialog; //
指向shell32.dll库中显示关机对话框函数的指针
if(hInst != NULL)
{
    //
获得函数的地址并调用之
    ShutDownDialog = (SHUTDOWNDLG)GetProcAddress(hInst,(LPSTR)60);
    
    (*ShutDownDialog)(0);
}

//五、枚举所有字体

LOGFONT lf;
lf.lfCharSet = DEFAULT_CHARSET; // Initialize the LOGFONT structure
strcpy(lf.lfFaceName,"");
CClientDC dc (this);
// Enumerate the font families
::EnumFontFamiliesEx((HDC) dc,&lf, (FONTENUMPROC) EnumFontFamProc,(LPARAM) this,0);
//
枚举函数
int CALLBACK EnumFontFamProc(LPENUMLOGFONT lpelf,
                             LPNEWTEXTMETRIC lpntm,DWORD nFontType,long lparam)
                             
{
    // Create a pointer to the dialog window
    CDay7Dlg* pWnd = (CDay7Dlg*) lparam;
    // add the font name to the list box
    pWnd ->m_ctlFontList.AddString(lpelf ->elfLogFont.lfFaceName);
    // Return 1 to continue font enumeration
    return 1;
}

//
其中m_ctlFontList是一个列表控件变量

//六、一次只运行一个程序实例,如果已运行则退出

if( FindWindow(NULL,"
程序标题")) exit(0);

//七、得到当前鼠标所在位置

CPoint pt;
GetCursorPos(&pt); //
得到位置

//八、上下文菜单事件触发事件 OnContextMenu事件

//九、显示和隐藏程序菜单

CWnd *pWnd=AfxGetMainWnd();
if(b_m) //
隐藏菜单
{
    pWnd->SetMenu(NULL);
    pWnd->DrawMenuBar();
    b_m=false;
}
else
{
    CMenu menu;
    menu.LoadMenu(IDR_MAINFRAME); ////
显示菜单 也可改变菜单项
    pWnd->SetMenu(&menu);
    pWnd->DrawMenuBar();
    b_m=true;
    menu.Detach();
}

//十、获取可执行文件的图标

HICON hIcon=::ExtractIcon(AfxGetInstanceHandle(),_T("NotePad.exe"),0);
if (hIcon &&hIcon!=(HICON)-1)
{
    pDC->DrawIcon(10,10,hIcon);
    
}
DestroyIcon(hIcon);

//十一、窗口自动靠边程序演示

BOOL AdjustPos(CRect* lpRect)
{//
自动靠边
    int iSX=GetSystemMetrics(SM_CXFULLSCREEN);
    int iSY=GetSystemMetrics(SM_CYFULLSCREEN);
    RECT rWorkArea;
    BOOL bResult = SystemParametersInfo(SPI_GETWORKAREA, sizeof(RECT), &rWorkAre
        a, 0);
    CRect rcWA;
    if(!bResult)
    {//
如果调用不成功就利用GetSystemMetrics获取屏幕面积
        rcWA=CRect(0,0,iSX,iSY);
    }
    else
        rcWA=rWorkArea;
    int iX=lpRect->left;
    int iY=lpRect->top;
    
    if(iX < rcWA.left + DETASTEP && iX!=rcWA.left)
    {//
调整左
        //pWnd->SetWindowPos(NULL,rcWA.left,iY,0,0,SWP_NOSIZE);
        lpRect->OffsetRect(rcWA.left-iX,0);
        AdjustPos(lpRect);
        return TRUE;
    }
    if(iY < rcWA.top + DETASTEP && iY!=rcWA.top)
    {//
调整上
        //pWnd->SetWindowPos(NULL ,iX,rcWA.top,0,0,SWP_NOSIZE);
        lpRect->OffsetRect(0,rcWA.top-iY);
        AdjustPos(lpRect);
        return TRUE;
    }
    if(iX + lpRect->Width() > rcWA.right - DETASTEP && iX !=rcWA.right-lpRect->Width())
    {//
调整右
        //pWnd->SetWindowPos(NULL ,rcWA.right-rcW.Width(),iY,0,0,SWP_NOSIZE);
        lpRect->OffsetRect(rcWA.right-lpRect->right,0);
        AdjustPos(lpRect);
        return TRUE;
    }
    if(iY + lpRect->Height() > rcWA.bottom - DETASTEP && iY !=rcWA.bottom-lpRect
        ->Height())
    {//
调整下
        //pWnd->SetWindowPos(NULL ,iX,rcWA.bottom-rcW.Height(),0,0,SWP_NOSIZE);
        lpRect->OffsetRect(0,rcWA.bottom-lpRect->bottom);
        return TRUE;
    }
    return FALSE;
}
//
然后在ONMOVEING事件中使用所下过程调用

CRect r=*pRect;
AdjustPos(&r);
*pRect=(RECT)r;

//十二、给系统菜单添加一个菜单项给系统菜单添加一个菜单项
需要进行下述三个步骤:
//
首先,使用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<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);
    //…
}

//十三、运行其它程序

//1
、运行EMAIL或网址

char szMailAddress[80];
strcpy(szMailAddress,"mailto:[email protected]");
ShellExecute(NULL, "open", szMailAddress, NULL, NULL, SW_SHOWNORMAL);

//2
、运行可执行程序
WinExec("notepad.exe",SW_SHOW); //
运行计事本

//十四、动态增加或删除菜单

//1
、 增加菜单
//
添加
CMenu *mainmenu;
mainmenu=AfxGetMainWnd()->GetMenu(); //
得到主菜单
(mainmenu->GetSubMenu (0))->AppendMenu (MF_SEPARATOR);//
添加分隔符
(mainmenu->GetSubMenu (0))->AppendMenu(MF_STRING,ID_APP_ABOUT,
                                        _T("Always on &Top")); //
添加新的菜单项
                                        DrawMenuBar(); //
重画菜单
//2
、 删除菜单
//
删除
CMenu *mainmenu;
mainmenu=AfxGetMainWnd()->GetMenu(); //
得到主菜单

CString str ;
for(int i=(mainmenu->GetSubMenu (0))->GetMenuItemCount()-1;i>=0;i--) //
取得菜单的项数。
{
    (mainmenu->GetSubMenu (0))->GetMenuString(i,str,MF_BYPOSITION);
    //
将指定菜单项的标签拷贝到指定的缓冲区。MF_BYPOSITION的解释见上。
    if(str=="Always on &Top") //
如果是刚才我们增加的菜单项,则删除。
    {
        (mainmenu->GetSubMenu (0))->DeleteMenu(i,MF_BYPOSITION);
        break;
    }
}

//十五、改变应用程序的图标静态更改

//
修改图标资源IDR_MAINFRAME。它有两个图标,一个是16*16的,另一个是32*32的,注意要一起修改。

//
动态更改: 向主窗口发送WM_SETICON消息.代码如下:
HICON hIcon=AfxGetApp()->LoadIcon(IDI_ICON);
ASSERT(hIcon);
AfxGetMainWnd()->SendMessage(WM_SETICON,TRUE,(LPARAM)hIcon);

//十六、另一种改变窗口标题的方法

//
使用语句 CWnd* m_pCWnd = AfxGetMainWnd( ),然后,再以如下形式调用SetWindowText()函数:
SetWindowText( *m_pCWnd,(LPCTSTR)m_WindowText);// m_WindowText
可以是一个CString类的变量。

//十七、剪切板上通过增强元文件拷贝图像数据
下面代码拷贝通过元文件拷贝图像数据到任何应用程序,
//
其可以放置在CView派生类的函数中。

CMetaFileDC * m_pMetaDC = new CMetaFileDC();
m_pMetaDC->CreateEnhanced(GetDC(),NULL,NULL,"whatever");
//draw meta file
//do what ever you want to do: bitmaps, lines, text...
//close meta file dc and prepare for clipboard;
HENHMETAFILE hMF = m_pMetaDC->CloseEnhanced();
//copy to clipboard
OpenClipboard();
EmptyClipboard();
::SetClipboardData(CF_ENHMETAFILE,hMF);                                                                                
CloseClipboard();

//DeleteMetaFile(hMF);
delete m_pMetaDC;

//十八、剪切板上文本数据的传送把文本放置到剪接板上

CString source;
//put your text in source
if(OpenClipboard())
{
    HGLOBAL clipbuffer;
    char * buffer;
    EmptyClipboard();
    clipbuffer = GlobalAlloc(GMEM_DDESHARE, source.GetLength()+1);
    buffer = (char*)GlobalLock(clipbuffer);
    strcpy(buffer, LPCSTR(source));
    GlobalUnlock(clipbuffer);
    SetClipboardData(CF_TEXT,clipbuffer);
    CloseClipboard();
}

//
从剪接板上获取文本:

char * buffer;
if(OpenClipboard())
{
    buffer = (char*)GetClipboardData(CF_TEXT);
    //do something with buffer here
    //before it goes out of scope
}
CloseClipboard();

//十九、将捕捉屏幕图像到剪切版中

void CShowBmpInDlgDlg::OnCutScreen()
{
    ShowWindow(SW_HIDE);
    RECT r_bmp={0,0,::GetSystemMetrics(SM_CXSCREEN),
        ::GetSystemMetrics(SM_CYSCREEN)};                                                                                      
    HBITMAP hBitmap;
    hBitmap=CopyScreenToBitmap(&r_bmp);
    
    //hWnd
为程序窗口句柄
    if (OpenClipboard())
    {
        EmptyClipboard();
        SetClipboardData(CF_BITMAP, hBitmap);
        CloseClipboard();
    }
    ShowWindow(SW_SHOW);
}
HBITMAP CShowBmpInDlgDlg::CopyScreenToBitmap(LPRECT lpRect)
{
    //lpRect
代表选定区域
    {
        HDC hScrDC, hMemDC;
        //
屏幕和内存设备描述表
        HBITMAP hBitmap, hOldBitmap;
        //
位图句柄
        int nX, nY, nX2, nY2;
        //
选定区域坐标
        int nWidth, nHeight;
        //
位图宽度和高度
        int xScrn, yScrn;
        //
屏幕分辨率
        
        //
确保选定区域不为空矩形
        if (IsRectEmpty(lpRect))
            return NULL;
        //
为屏幕创建设备描述表
        hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
        //
为屏幕设备描述表创建兼容的内存设备描述表
        hMemDC = CreateCompatibleDC(hScrDC);
        //
获得选定区域坐标
        nX = lpRect->left;
        nY = lpRect->top;
        nX2 = lpRect->right;
        nY2 = lpRect->bottom;
        //
获得屏幕分辨率
        xScrn = GetDeviceCaps(hScrDC, HORZRES);
        yScrn = GetDeviceCaps(hScrDC, VERTRES);
        //
确保选定区域是可见的
        if (nX<0)
            
            nX = 0;
        if (nY<0)
            nY = 0;
        if (nX2>xScrn)
            nX2 = xScrn;
        if (nY2>yScrn)
            nY2 = yScrn;
        nWidth = nX2 - nX;
        nHeight = nY2 - nY;
        //
创建一个与屏幕设备描述表兼容的位图
        hBitmap = CreateCompatibleBitmap
            (hScrDC, nWidth, nHeight);
        //
把新位图选到内存设备描述表中
        hOldBitmap =(HBITMAP)SelectObject(hMemDC, hBitmap);
        //
把屏幕设备描述表拷贝到内存设备描述表中
        BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);
        //
得到屏幕位图的句柄
        hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
        
        //
清除
        DeleteDC(hScrDC);
        DeleteDC(hMemDC);
        //
返回位图句柄
        return hBitmap;
    }
}

//二十、如何将位图缩放显示在Static控件中

//
Staic控件内显示位图
void CShowBmpInDlgDlg::ShowBmpInStaic()
{
    CBitmap hbmp;
    HBITMAP hbitmap;
    //
pStatic指向要显示的地方
    CStatic *pStaic;
    pStaic=(CStatic*)GetDlgItem(IDC_IMAGE);
    //
装载资源 MM.bmp是我的一个文件名,用你的替换
    hbitmap=(HBITMAP)::LoadImage (::AfxGetInstanceHandle(),"MM.bmp",
        IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
    
    hbmp.Attach(hbitmap);
    //
获取图片格式
    BITMAP bm;
    hbmp.GetBitmap(&bm);
    CDC dcMem;
    dcMem.CreateCompatibleDC(GetDC());
    CBitmap *poldBitmap=(CBitmap*)dcMem.SelectObject(hbmp);
    CRect lRect;
    pStaic->GetClientRect(&lRect);
    //
显示位图
    pStaic->GetDC()->StretchBlt(lRect.left ,lRect.top ,lRect.Width(),lRect.Height(),
        &dcMem,0 ,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
    dcMem.SelectObject(&poldBitmap);
}
 
窗口
让窗口一启动就最大化
把应用程序类(CxxxApp)的 InitInstance() 函数中的
m_pMainWnd->ShowWindow(SW_SHOW);
改为
m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
则窗口一启动就最大化显示。

如何设置窗口的初始尺寸
在将应用程序类(CxxAPP)的 InitInstance() 函数中加入:
m_pMainWnd->SetWindowPos(NULL,x,y,Width,Height,SWP_NOMOVE);
Width
为窗口宽度,Height为窗口高度
SWP_NOMOVE
表示忽略位置(x,y)
如:

让窗口居中显示
以下两种方法可任选其一:
在应用程序类(CxxxApp)的 InitInstance() 函数中加入:
在主框架类(MainFrm.cpp)OnCreate()函数中加入:
CenterWindow( GetDesktopWindow() );
如:如何修改窗口标题
窗口标题一般形式为:文档标题 - 程序标题
1
、设置文档标题:
在文档类(CxxxDoc)OnNewDocument()函数中加入语句:SetTitle("文档名");
如:TextEditorDoc.cpp可删除Debug文件夹和Release文件夹;
原则上还可删除主文件夹中所有图标为 的文件,包括.aps.ncb.opt.plg等文件,它们都能在编译时重建。但一般.clw不要删除,它可能导致ClassWizard不好用。



控件
如何隐藏和显示控件
CWnd类的函数BOOL ShowWindow(int nCmdShow)可以隐藏或显示一个控件。
1
CWnd *pWnd;
pWnd = GetDlgItem( IDC_EDIT1 ); //
获取控件指针,IDC_EDIT为控件ID
pWnd->ShowWindow( SW_HIDE ); //
隐藏控件
2
CWnd *pWnd;
pWnd = GetDlgItem( IDC_EDIT1 ); //
获取控件指针,IDC_EDIT为控件ID
pWnd->ShowWindow( SW_SHOW ); //
显示控件

按钮的使能与禁止
ClassWizardMember Variables为按钮定义变量,如:m_Button1

m_Button1.EnableWindow(true);
使按钮处于允许状态
m_Button1.EnableWindow(false);
使按钮被禁止,并变灰显示

改变控件的大小和位置
CWnd类的函数MoveWindow()SetWindowPos()可以改变控件的大小和位置。
void MoveWindow(int x,int y,int nWidth,int nHeight);
void MoveWindow(LPCRECT lpRect);
第一种用法需给出控件新的坐标和宽度、高度;
第二种用法给出存放位置的CRect对象;
例:
CWnd *pWnd;
pWnd = GetDlgItem( IDC_EDIT1 ); //
获取控件指针,IDC_EDIT1为控件ID
pWnd->MoveWindow( CRect(0,0,100,100) ); //
在窗口左上角显示一个宽100、高100的编辑控件
SetWindowPos()
函数使用更灵活,多用于只修改控件位置而大小不变或只修改大小而位置不变的情况:
BOOL SetWindowPos(const CWnd* pWndInsertAfter,int x,int y,int cx,int cy,UINT nFlags);
第一个参数一般设为NULL;
x
y控件位置;cxcy控件宽度和高度;
nFlags
常用取值:
SWP_NOZORDER
:忽略第一个参数;
SWP_NOMOVE
:忽略xy,维持位置不变;
SWP_NOSIZE
:忽略cxcy,维持大小不变;
例:
CWnd *pWnd;
pWnd = GetDlgItem( IDC_BUTTON1 ); //
获取控件指针,IDC_BUTTON1为控件ID
pWnd->SetWindowPos( NULL,50,80,0,0,SWP_NOZORDER | SWP_NOSIZE ); //
把按钮移到窗口的(50,80)
pWnd = GetDlgItem( IDC_EDIT1 );
pWnd->SetWindowPos( NULL,0,0,100,80,SWP_NOZORDER | SWP_NOMOVE ); //
把编辑控件的大小设为(100,80),位置不变
pWnd = GetDlgItem( IDC_EDIT1 );
pWnd->SetWindowPos( NULL,0,0,100,80,SWP_NOZORDER ); //
编辑控件的大小和位置都改变
以上方法也适用于各种窗口。

单选按钮控件(Radio Button)的使用
一、对单选按钮进行分组:
每组的第一个单选按钮设置属性:GroupTabstopAuto;其余按钮设置属性TabstopAuto
如:
Radio1
Radio2Radio3为一组,Radio4Radio5为一组
设定Radio1属性:GroupTabstopAuto
设定Radio2属性:TabstopAuto
设定Radio3属性:TabstopAuto
设定Radio4属性:GroupTabstopAuto
设定Radio5属性:TabstopAuto
二、用ClassWizard为单选控件定义变量,每组只能定义一个。如:m_Radio1m_Radio4
三、用ClassWizard生成各单选按钮的单击消息函数,并加入内容:
void CWEditView::OnRadio1()
{
m_Radio1 = 0; //
第一个单选按钮被选中
}
void CWEditView::OnRadio2()
{
m_Radio1 = 1; //
第二个单选按钮被选中
}
void CWEditView::OnRadio3()
{
m_Radio1 = 2; //
第三个单选按钮被选中
}
void CWEditView::OnRadio4()
{
m_Radio4 = 0; //
第四个单选按钮被选中
}
void CWEditView::OnRadio5()
{
m_Radio4 = 1; //
第五个单选按钮被选中
}
当控件变量值为0时,它对应组的第一个单选按钮处于选中状态。
BOOL CDzyApp::InitInstance()
...{
AfxEnableControlContainer();
……

// The one and only window has been initialized, so show and update it.
m_pMainWnd->SetWindowPos(NULL,0,0,750,555,SWP_NOMOVE);//
设置窗口的初始大小为750*555
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();

return TRUE;
}
m_pMainWnd->CenterWindow( GetDesktopWindow() );
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
……

// TODO: Delete these three lines if you don't want the toolbar to
// be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);

CenterWindow( GetDesktopWindow() ); //
使窗口打开时处于屏幕正中

return 0;
}
BOOL CTextEditorDoc::OnNewDocument() {
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
SetTitle("
未命名.txt"); //设置文档标题
return TRUE;
}

2
、设置程序标题:
在框架类(CMainFrame)PreCreateWindow()函数中加入语句:m_strTitle = _T("程序标题");
如:MainFrm.cpp
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) {
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
cs.style&=~FWS_ADDTOTITLE;//
去除标题栏文字前面的"无标题"
m_strTitle = _T("
文本整理器"); //设置程序标题
return TRUE;
}
以上两点比较适用于视图-文档结构的程序,在新建文档时,系统会自动运行OnNewDocument()函数,在其中可以设置合适的标题。对于未采用文档的程序可以用下面的方法修改标题:
3
、修改窗口标题:
修改窗口标题一般在打开文件函数OnFileOpen()和另存为函数OnFileSaveAs()中进行,可以使用下面的函数:其中文档标题和程序标题可使用定义过的串变量。
 
如何干净的删除一个类
1
、先删除项目中对应的.h.cpp文件,(选中后用Delete键删除)
2
、保存后退出项目,到文件夹中删除实际的.h.cpp文件;
3
、删除.clw文件;
4
、重新进入项目,进行全部重建(rebuild all)。

如何建立一个新类?
    
插入”(Insert)菜单中选择新建类”(New Class),在弹出的对话框中选择基类(Base class),在Name中输入新类的名字(一般都以C开头)即可。
如果想要建立一个没有基类的自定义类,则在New Class对话框中把Class type设置为generic,再输入类名即可。

如何把外来文件添加到项目中
    
先把外来文件复制到当前项目的目录下,从项目”(Project)菜单下选择添加项目”(Add to Project)下的“Files”菜单项,从弹出的打开文件对话框中把外来文件打开即可。

如何在一个工作区中打开多个项目
    
一般编程者都有这样的经历:做了一个项目,由于不满意,想从头重做,但又想把旧项目的一些可用内容拷到新项目中来,以免做重复工作,这时就需要在新项目中打开旧项目。
    
先打开新项目,从项目”(Project)菜单下选择插入项目到工作区”(Insert Project into Workspace),从弹出的打开文件对话框中打开旧项目的.asp文件即可。
    
之后,可以利用项目”(Project)菜单下的设置活动项目”(Select Active Project)的选项中切换各打开的项目。
注意:在一个工作区中打开的各项目不能同名。

如何把项目中的文件分类存放?
当我们往项目中添加新类时,它会把源文件放在Source Files下,头文件放在Header Files下。当项目中文件很多时,管理不便,最好添加新节点,把文件分类放置。
右击项目节点树的根节点,选择“New Folder...”,在弹出的对话框中填入新节点名,则新节点就建立了,用鼠标节点树中的文件拖入新节点,就可以把文件分类了。
以上分类只是在项目的节点树中分类,它不影响文件在磁盘上的位置,所有.cpp文件和.h文件仍在项目的根目录下,最好文件本身也能分类存放在不同文件夹中。
Windows下,用新建文件夹在项目的根目录下建立子文件夹,如DialogClass,把所有对话框类的.cpp文件和.h文件拖入其中。
回到VC下,右键单击项目树中更改了路径的节点,选择“Properties”,在弹出的对话框中修改文件路径,如:把原路径“.\Dialog1.cpp”改为“.\DialogClass\Dialog1.cpp”
打开Dialog1.cpp文件,修改它包含的文件路径。如:
i nclude "stdafx.h"
i nclude "PluckBox.h"
i nclude "Dialog1.h"
改为:
i nclude "stdafx.h"
i nclude "..\\PluckBox.h"
i nclude "Dialog1.h"
打开ClassWizard,它会提示你文件不存在,单击确定后,从对话框中用“Browse...”选择文件所在路径,则ClassWizard也可正常使用了。



编辑
编辑代码时,跟随提示消失了怎么办?
单 击工具”(Tools)菜单中的设置”(Options)菜单项,在弹出的Options对话框中选择Editor制表页,把它最下方的四个复选框都 选中(Auto list memberAuto type infoCode commentsAuto parameter info),这样,当用户输入“->”“.”时,会自动显示跟随提示,减少了输入负担。



对话框
如何修改对话框的背景色
在对话框的OnPaint()函数中加入下面语句:
CRect rect;
GetClientRect(&rect); //
计算对话框的尺寸
dc.FillSolidRect(&rect,RGB(192,248,202)); //
绘制对话框背景色

如何让弹出式对话框具有统一的背景色
在应用程序类CxxxAppInitInstance()函数中加入下面的语句:
SetDialogBkColor( RGB(192,248,202) );
则所有用户定义的弹出式对话框都以RGB(192,248,202)为背景色,就不需要逐个进行设置了。


如何让打开文件对话框能进行多项选择
在定制打开文件对话框时,增加OFN_ALLOWMULTISELECT属性,就可以使打开文件对话框进行多选了。
如:
CFileDialog m_Dlg( TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT
| OFN_ALLOWMULTISELECT, NULL, NULL );
之后,用GetStartPosition()函数获取选择的起始文件位置,用GetNextPathName()函数获取各位置上的文件名。
如:
if( m_Dlg.DoModal() == IDOK )
{
POSITION pos;
pos = m_Dlg.GetStartPosition();
while( pos )
{
m_Path = m_Dlg.GetNextPathName(pos);
…………
}
}

为什么用打开文件对话框选择多个文件到一定数目时,文件没有打开?
CFileDialog
为文件列表设置有缓冲区,当选择文件过多时,会造成缓冲区溢出,造成一些文件没有被打开。可以采用自定义大缓冲区代替系统缓冲区的方法解决。
如:
CFileDialog m_Dlg( TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT
| OFN_ALLOWMULTISELECT, NULL, NULL );//
定制打开文件对话框
char* pBuf = new char[20480]; //
申请缓冲区
m_Dlg.m_ofn.nMaxFile = 20480; //
pBuf代替CFileDialog缓冲区
m_Dlg.m_ofn.lpstrFile = pBuf;
m_Dlg.m_ofn.lpstrFile[0] = NULL;
…………
delete []pBuf; //
回收缓冲区

提示对话框(MessageBox
在视类和对话框类中可使用MFC函数中用的MessageBox()函数弹出提示对话框。这个函数原型为:
int MessageBox(LPCTSTR lpszText,LPCTSTR lpsCaption=NULL,UINT nType=MB_OK);
参数:lpszText 显示的字符串
lpsCaption
对话框的标题
nType
风格,可为如下值的组合:
指定下列标志中的一个来显示消息框中的按钮,标志的含义如下。
MB_ABORTRETRYIGNORE
:消息框含有三个按钮:AbortRetryIgnore
MB_OK
:消息框含有一个按钮:OK。这是缺省值。
MB_OKCANCEL
:消息框含有两个按钮:OKCancel
MB_RETRYCANCEL
:消息框含有两个按钮:RetryCancel
MB_YESNO
:消息框含有两个按钮:YesNo
MB_YESNOCANCEL
:消息框含有三个按钮:YesNoCancel
指定下列标志中的一个来显示消息框中的图标:标志的含义如下。
MB_ICONEXCLAMATION:
MB_ICONWARNING
:一个惊叹号出现在消息框。
MB_ICONINFORMATION

MB_ICONASTERISK
:一个圆圈中小写字母i组成的图标出现在消息框。
MB_ICONOUESTION:
一个问题标记图标出现在消息框。
MB_ICONSTOP:
MB_ICONERROR

MB_ICONHAND
:一个停止消息图标出现在消息框。
指定下列标志中的一个来指定缺省的按钮:标志的含义如下。
MB_DEFBUTTON1
:第一个按钮为缺省按钮。如果MB_DEFBUTTON2MB_DEFBUTTON3MB_DEFBUTTON4没有被指定,则MB_DEFBUTTON1为缺省值。
MB_DEFBUTTON2
;第二个按钮为缺省按钮。
MB_DEFBUTTON3
:第三个按钮为缺省按钮。
MB_DEFBUTTON4
:第四个按钮为缺省按钮。
例:提示文件是否存盘:
int t;
t=MessageBox(m_PathName+"
的文字已经改变,要存盘吗?",
"
警告",MB_YESNOCANCEL | MB_ICONWARNING);
if(t==0 || t==IDCANCEL)
return;
if(t==IDYES)
OnFileSave();
在文档类等其它类中不能使用MFC中的MessageBox()函数,只能使用API函数中的MessageBox()函数:
int MessageBox(HWND hWnd,LPCTSTR lpszText,LPCTSTR lpCaption,UINT UType);
hWnd:
标识将被创建的消息框的拥有窗口。如果此参数为NULL,则消息框没有拥有窗口。
后三个参数与视类的MessageBox相同,但没有缺省值,必须设置。
例:::MessageBox(NULL,m_PathName+"的文字已经改变,要存盘吗?",
"
警告",MB_YESNOCANCEL | MB_ICONWARNING);



调试
error C2146: syntax error : missing ';' before identifier ……
如果出现这个错误且错误数目很多,通常并不是缺失了分号引起的,而是忘记了添加某头文件引起的。
最常见的是新加入了对话框,然后用它的类定义了一个对象,再编译出现上面的错误。
解决方法是在引用新类的文件中加入#i nclude "类名.h",再编译,错误消失。

fatal error C1010: unexpected end of file while looking for precompiled header directive
在一个项目中,如果用“New”向工程中添加了一个.cpp文件,编译,出错。
解决方法:
                   1)  
在新建的.cpp文件的开头加入#i nclude "stdafx.h"
                   2)  
可以使用右键点击项目工程中的该cpp文件,选择setting,在c/c++栏,选择PreCompiled headers,然后设置第一选项,选择不使用预编译头,解决这个问题。发布
Debug模式和Release模式
早就发现用VC编译出来的.exe文件比用Turbo C编译出来的文件大了许多,于是就认为VC编译时一定加了很多没用的东西,记得当时还做过把VC自动生成的项目中自认为没用的函数都删掉的傻事。后来才从网上的文章中了解到还有编译模式一说。
Debug
模式是用来调试用的,它生成的执行文件中含有大量调试信息,所以很大;
Release
模式生成的执行文件消除了这些调试信息,可用来作为成品发布。
默 认情况下是Debug模式,切换方法是在编译”(Build)菜单中选设置项目配置”(Set Active Configure)。从弹出的对话框中选择Win32 Release模式,然后再重新编译。这时在工作目录下会多出一个Release目录,其中的exe文件比Debug目录下的那个要小得多。

动态链接库和静态链接库
VC 做好了一个程序,拿到别人那里却不能运行,这也是很多编程者都经历过的,这样的软件只能在安装有VC的机器上运行,也不应拿出去发布。实际上如果你没有使 用ActiveX控件和自定义的动态DLL技术,只需把MFC的动态链接库打包到你的程序里就可以了,也就是使用静态链接库。
设置方法:从项目”(Project)菜单下选择设置” (Settings),在弹出的对话框中的General选项卡下,把“User MFC in a Shared DLL”改为“User MFC in a Static Library”,关闭对话框后重新编译即可。
在静态链接库下编译的文件比动态链接库的要大很多,不过,如果使用Release模式编译,一般也就几百K,它就可以在没有安装VC的机器上运行了。

发布VC源代码时,哪些文件可以删除?
AfxGetMainWnd()->SetWindowText(" 文档标题"+" - "+"程序标题");

四、设置默认按钮
在定义控件变量时,ClassWizard在构造函数中会把变量初值设为-1,只需把它改为其它值即可。
如:
//{{AFX_DATA_INIT(CWEditView)
m_Ridio1 = 0; //
初始时第一个单选按钮被选中
m_Ridio4 = 0; //
初始时第四个单选按钮被选中
//}}AFX_DATA_INIT

旋转控件(Spin)的使用
当单击旋转控件上的按钮时,相应的编辑控件值会增大或减小。其设置的一般步骤为:
一、在对话框中放入一个Spin控件和一个编辑控件作为Spin控件的伙伴窗口
设置Spin控件属性:Auto buddySet buddy integerArrow keys
设置文本控件属性:Number
二、用ClassWizardSpin控件定义变量m_Spin,为编辑控件定义变量m_Edit,定义时注意要把m_Edit设置为int型。
三、在对话框的OnInitDialog()函数中加入语句:
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();

m_Spin.SetBuddy( GetDlgItem( IDC_EDIT1 ) ); //
设置编辑控件为Spin控件的伙伴窗口
m_Spin.SetRange( 0, 10 ); //
设置数据范围为0-10
return TRUE;
}
四、用ClassWizard为编辑控件添加EN_CHANGE消息处理函数,再加入语句:
void CMyDlg::OnChangeEdit1()
{
m_Edit = m_Spin.GetPos(); //
获取Spin控件当前值
}

UpdateData()
对于可以接收数据的控件,如编辑控件来说,UpdateData()函数至关重要。当控件内容发生变化时,对应的控件变量的值并没有跟着变化,同样,当控件变量值变化时,控件内容也不会跟着变。
UpdateData()
函数就是解决这个问题的。
UpdateData(true);
把控件内容装入控件变量
UpdateData(false);
用控件变量的值更新控件
如:有编辑控件IDC_EDIT1,对应的变量为字符串m_Edit1
1 、修改变量值并显示在控件中
m_Edit1 = _T(" 结果为50");
UpdateData(false);
2 、读取控件的值到变量中:
ClassWizardIDC_EDIT1添加EN_CHANGE消息处理函数,这个函数在编辑控件内容发生变化时执行。
void CEditView::OnChangeEdit1()
{
UpdateData(true); //
更新变量值
}



其它
如何获取程序所在的路径
也就是获取你这个程序本身所在的路径。
在应用程序类CxxApp的头文件中定义一个变量CString m_exePath;用来放置程序的路径名,在应用程序类CxxAppInitInstance()函数中加入如下语句:
TCHAR m_Path[MAX_PATH];
GetModuleFileName( NULL, m_Path, MAX_PATH ); //
获取程序路径(包括程序名)
int i = 0, j;
while( m_Path[i]!=0 )
{
if( m_Path[i]=='\\' )
j = i;
i++;
}
m_Path[j+1] = '\0';
m_exePath.Format( "%s", m_Path ); //
分离路径名(去掉程序名)
这段程序执行后,字符串变量m_exePath中放置的就是程序所在路径,其中不包括程序名。
获取程序的位置有什么用呢?
1
、打开与应用程序在一起放置的数据文件:
如果你运行程序过程中使用过打开文件对话框打开过其它路径下的文件,这时系统的默认路径就发生了改变,有可能使你原定的数据文件打不开了,如果采用以下方法就可以没问题了:
CFile file;
file.Open( m_exePath+"
数据文件名", CFile::modeRead );
2
、放置程序运行中的临时文件:
同样,当系统的默认路径发生改变后,程序中生成的临时文件就会放得到处都是,成了一个个垃圾文件,采用以下方法可使临时文件只放在程序所在路径下:
CFile file;
file.Open( m_exePath+"
临时文件名", CFile::modeCreate | CFile::modeWrite );
……
程序结束时,用下面的方法删除临时文件:
CFile::Remove( m_exePath+"
临时文件名" );

如何在你的程序中执行其它程序
在自己的程序中调用其它程序的方法有好几种,这里我介绍我用过的两种:
一、WinExec()函数:
一般用法:WinExec(m_PathName,SW_SHOWNORMAL);
m_PathName
为执行程序的路径名,必须为可执行文件。
如:WinExec("C:\\Program Files\\Internet Explorer\\iexplore.exe",SW_SHOWNORMAL);为打开IE浏览器

二、ShellExecute()函数:
一般用法:ShellExecute(NULL,NULL,m_PathName,NULL,_T("c:\\temp"),SW_SHOWNORMAL);
m_PathName
为打开的程序路径名;
_T("c:\\temp")
为工作目录;
WinExec()不同的是ShellExecute()函数也可以打开非可执行文件,比如你指定的文件为.txt,结果会打开记事本装入该文件。我用这种方法调用自己制作的帮助文件(.chm)效果很好。

如果不使用串行化,如何在程序结束时保存文件?
在文档-视图结构中,用串行化自动保存文件在各种VC书上都有介绍。现在的问题是我不使用串行化,而是自己动手保存,当点击窗口的关闭按钮时,如何提示并保存文档。
ClassWizard在文档类(CxxDoc)中添加函数CanCloseFrame(),再在其中加入保存文件的语句就可以了。
例:
//
退出程序
BOOL CEditDoc::CanCloseFrame(CFrameWnd* pFrame)
{
CFile file;
if(b_Flag) //b_Flag
为文档修改标志,在修改文档时将其置为True
{
int t;
t=::MessageBox(NULL,"
文字已经改变,要存盘吗?","警告",
MB_YESNOCANCEL | MB_ICONWARNING); //
弹出提示对话框
if(t==0 || t==IDCANCEL)
return false;
if(t==IDYES)
{
CString sFilter="Text File(*.txt)|*.txt||";
CFileDialog m_Dlg(FALSE,"txt",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,(LPCTSTR)sFilter,NULL); //
定制文件对话框
int k=m_Dlg.DoModal(); //
弹出文件对话框
if(k==IDCANCEL || k==0)
return false;
m_PathName=m_Dlg.GetPathName(); //
获取选择的文件路径名

file.Open(m_PathName,CFile::modeCreate | CFile::modeWrite);
file.Write(m_Text,m_TextLen); //
数据写入文件
file.Close();
}
}
return CDocument::CanCloseFrame(pFrame);
}
这样当你单击窗口上的关闭按钮时,如果数据已修改了,就会弹出一个提示保存数据的对话框,提示你保存数据。
程序中的b_Flag是数据修改标志,应该在修改数据时进行设置,m_Text是准备保存的数据,放在文档内。

POSITION怎么用
POSITION
类型数据用于表征各种列表中元素的位置,它类似于数组的下标,但又有所不同。主要区别是:
我们不能访问POSITION型数据的值,也不能对POSITION数据型数据进行加减、比较等运算。
POSITION型数据访问列表时,都是采用迭代法,一般格式为:
POSITION pos; //
定义pos型变量
pos = GetHeadPosition(); //
获取列表起始元素位置
while( pos )
{
x = GetNext(pos); //
获取pos处的列表值,同时修改pos为下一个元素位置
}
GetNext()
就是一种迭代,其格式为:
TYPE GetNext(POSITION& rPosition);
首先,它返回当前pos位置处的元素;再就是把pos值修改为下一个元素位置。这样循环时,可依次取得列表中各元素的值;当到达列表尾时,posNULL,循环结束。
所以使用POSITION型数据时,你不要试图用加减等操作去修改它,只能用GetNext()(向后迭代)或GetPrev()(向前迭代)反复迭代来修改它的值。
如果你想直接到达指定值,还可以用Find()函数或FindIndex()函数获得指定值的POSITION值。
POSITION Find(TYPE Value);
用于在列表中查找值为Value的元素的POSITION值;
POSITION FindIndex(int nIndex);
用于获取列表中第nIndex个元素的POSITION值,nIndex0开始。
如:
pos = FindIndex(5); //
求列表中第5个元素的位置
x = GetNext(pos); //
读取元素的值
总之,POSITION类型在多种涉及列表的类中提供,不同的类提供的函数有所不同,但用法都是类似的。

如何从完整的文件路径中分离文件名和路径名
从路径中分离文件名:

CString GetFileName(CString pathname)
{
for( int i=pathname.GetLength()-1; i>=0; i-- )
{
if( pathname[i]=='\\' )
break;
}
return pathname.Mid( i+1 );
}
从路径中分离路径名(去除文件名):

CString GetPath(CString pathname)
{
int i = 0, j;
while( i<pathname.GetLength() )
{
if( pathname[i]=='\\' )
j = i;
i++;
}
return pathname.Left( j+1 );
 

VC中添加响应自定义的消息的代码步骤

 1. 首先定义一个消息代码
#define WM_DEBUG WM_USER 1999

  2. 在窗口头文件中添加
class CStreamServerDlg : public CDialog
{
// Generated message map functions
//{{AFX_MSG(CStreamServerDlg)
...
//}}AFX_MSG
afx_msg void OnDebug(WPARAM wParam, LPARAM lParam);
...
}

  3. 在窗口的cpp文件中添加
BEGIN_MESSAGE_MAP(CStreamServerDlg, CDialog)
...
ON_MESSAGE(WM_DEBUG, OnDebug)
END_MESSAGE_MAP()

void CStreamServerDlg::OnDebug(WPARAM wParam, LPARAM lParam)
{}

  4. 其他地方就可以发送消息
pWnd->PostMessage(WM_DEBUG, (WPARAM)p, 0) )
 
禁止调整窗口大小(MFC)
 
GDI绘画代码:

 HDC hDC = ::CreateCompatibleDC(pDC->GetSafeHdc());
 SelectObject(hDC,m_bmpBack);
 CBitmap bitmap;  
 bitmap.LoadBitmap(IDB_CARDS);  
 CDC MemDC;  
 MemDC.CreateCompatibleDC(pDC);  
 CBitmap *pOldBitmap=MemDC.SelectObject(&bitmap);  
 BITMAP bm;  
 bitmap.GetBitmap(&bm);  
 CRect rect;
 this->GetClientRect(rect);
 pDC->StretchBlt(0,0,rect.right,rect.bottom,&MemDC,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);  
 MemDC.SelectObject(pOldBitmap);

/////////////////////////////

HDC hDC = ::CreateCompatibleDC(pDC->GetSafeHdc());

 CPoint pt;
 RECT rc;
 GetClientRect(&rc);

 HBITMAP hOldBmp = (HBITMAP)::SelectObject(hDC, m_bmpCards);
 BITMAP bmp;
 CBitmap::FromHandle(m_bmpCards)->GetBitmap(&bmp);

 int width = bmp.bmWidth / 13;  //每张牌的宽度和高度.
 int height = bmp.bmHeight / 4;


 //画1号位扑克  左上1,左中2 自己3,右中4,右上5
 for (BYTE i=0; i<5; i++)
 {
  HBITMAP hBmp = m_bmpCardPlus;
  ::SelectObject(hDC, hBmp);

  BitBlt(pDC->GetSafeHdc(),m_pt[1].x,m_pt[1].y,width,height,hDC,0,0,SRCCOPY);

  m_pt[1].y += 20;
 }

一个好的函数 ,msdn未收的。

 //读取TXT一行并解析存放至结构体当中
   AfxExtractSubString( name, line, 0, '\t');

你可能感兴趣的:(小技巧)