VC開發小技巧

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) )

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章