VC++初學者常見問題解惑

                                   VC++初學者常見問題解惑
    李海 

Visual C++是功能非常強大的工具,但也是公認比較難於入門的。這裏,我們整理了一些初學者常見的問題,希望幫助那些剛剛接觸Visual C++的朋友享受編程的樂趣。

  問:我是一新手,請問我以前在TC++中寫的C++程序,在VC中要建立一個什麼樣的工程來運行它(程序在TC++是正確的)?

  

  答:在VC++中新建工程時,你可以選擇Win 32 Console Application。這種控制檯程序像DOS程序一樣工作並輸出文本信息,雖然不能使用圖形函數,但可以使用其它Windows API函數。要注意的是,如果你的TC++程序使用了非ANSI標準的語句,如Conio.h中的函數,可能需要進行一些修改才能在VC++下編譯。

  

  問:VC中有沒有類擬DoEvents的函數?

  

  答:你可以使用這樣的函數:

  BOOL CheckMessageQueue()

  {    MSG msg;

       while(PeekMessage(&&msg, NULL, 0, 0, PM_REMOVE)){

     if(msg.message==WM_QUIT)

         return FALSE;

       TranslateMessage(&&msg);

       DispatchMessage(&&msg);

      }

      return TRUE;

  }

  調用PeekMessage取消息時,其它程序將有機會獲得控制權,可以實現DoEvents的效果。但要注意這個函數返回值的含義,如果該函數返回FALSE,說明用戶按下了關閉按鈕。

  

  問:在不拷貝文件的情況下,如何在C/C++中去掉文件尾部,也就是快速剪短文件?

  

  答:在C/C++中,一般都有一個函數chsize或_chsize可以改變文件的大小。下面是一段例子:

   int fh, result;

   unsigned int nbytes = BUFSIZ;

   /* 打開文件 */

   if( (fh = _open( "c://testdata", _O_RDWR | _O_CREAT, _S_IREAD

         | _S_IWRITE )) != -1 )

   { printf( "修改前文件長度: %ld/n", _filelength( fh ) );

     if( ( result = _chsize( fh, 329678 ) ) == 0 )

  printf( "成功地修改了文件長度/n" );

     else

    printf( "改變文件長度出錯/n" );

     printf( "修改後文件長度: %ld/n", _filelength( fh ) );

     _close( fh );}}

  

  問:使用VC5.0將OBJ文件編譯成DLL後,用VB調用時總說找不到入口點。請問在什麼地方加入關於入口點的參數?

  

  答:找不到入口點有以下幾種情況:

  1.沒有注意函數名的大小寫

    在Win32中,DLL中的函數和VB中的函數必須大小寫完全相同,否則系統認爲DLL中沒有要調用的函數。

  2.沒有聲明入口函數

    你需要在DLL的.def文件中加上入口函數,如:

   EXPORTS

   SetData @1

   GetData @2

  這樣VB程序就可以訪問SetData和GetData函數了。其中@1、@2是這兩個函數的引用序號,通常在VB中不使用。如果你的DLL工程原本沒有使用.def文件,你可以建立一個文本文件,並命名爲.def擴展名存盤後加入到工程中。

  3.採用了C++編譯方式

    在C++中編譯函數時會將函數名進行轉換,如將DLL中的kk(double k)轉換爲_kk@8。解決的辦法有兩種:

  (1)如果沒有使用C++的類,可以將.cpp文件改名爲.c,就不進行這種轉換了。

  (2)在函數定義前加上extern "c",如:

  extern "c" void _stdcall kk(double k);

    需要指出的是,VC++允許不編寫.def文件,而是在函數定義前加__declspec(dllexport)修飾符,這樣的函數也可以被外部程序調用。但是這樣的函數都將會按C++方式進行函數名轉換。雖然這樣的函數可以被VB程序調用,但顯得不方便,所以仍然建議使用.def文件的辦法。

  

  問:使用VC++ 5.0,如何在程序中設置按下Caps Lock 鍵,使得使用者在某Edit框裏輸入的字母自動爲大寫,輸入後設置該鍵再按下,即恢復輸入小寫字母狀態。

  

  答:利用Windows API函數keybd_event可以模擬按下Caps Lock 鍵。下面的代碼能夠切換Caps Lock 鍵。

  void SetCapsLock( BOOL bState )

   {

     BYTE keyState[256];

     GetKeyboardState((LPBYTE)&&keyState);

     if( (bState &&&& !(keyState[VK_CAPITAL] && 1)) ||

       (!bState &&&& (keyState[VK_CAPITAL] && 1)) )

     {

     // 模擬按下一個鍵

       keybd_event( VK_CAPITAL,

             0x45,

   KEYEVENTF_EXTENDEDKEY | 0,

             0 );

     // 模擬放開一個鍵

       keybd_event( VK_CAPITAL,

             0x45,

  KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,

             0);

     }

   }

  // 當用戶切換到Edit1控件,設置爲大寫狀態

  void CDlgDlg::OnSetfocusEdit1()

  {SetCapsLock(TRUE);}

  // 當用戶離開Edit1控件,設置爲小寫狀態

  void CDlgDlg::OnKillfocusEdit1()

  { SetCapsLock(FALSE);}

  不過對於你的問題,我建議採用另一種方法,即重載PreTranslateMessage函數,用戶每輸入一個字母就將其自動轉換爲大寫,而不是修改Caps Lock 鍵,如:

  BOOL CDlgDlg::PreTranslateMessage(MSG* pMsg)

  { if(pMsg-〉message == WM_CHAR

   &&&& pMsg-〉hwnd == ::GetDlgItem(m_hWnd, IDC_EDIT1))

   { pMsg-〉wParam = toupper(pMsg-〉wParam);}

   return CDialog::PreTranslateMessage(pMsg);

  }

  

  問: 如何編程實現Windows關機的那個對話窗口?就是說,如果我按一個按鈕,就可以出現關機對話窗口,讓我選擇是否關機、重啓等等?而且背景也是那樣的灰暗。是否有一個現成的API可以調用?

  

  答:有一個未公開的API函數可以實現這個功能,是在Shell32.dll中,但沒有名字,索引號爲60。這種函數可以使用LoadLibrary和GetProcAddress函數進行調用。

  下面就是一個例子:

  typedef int (CALLBACK *SHUTDOWNDLG) (int);

  void CDlgDlg::OnOK() {

   CString s;

   HINSTANCE hInst = LoadLibrary("shell32");

   SHUTDOWNDLG SHShutDownDialog;

   if(hInst != 0)

   {

   // 獲得顯示關機對話框函數的地址並調用

   SHShutDownDialog = (SHUTDOWNDLG)GetProcAddress(hInst, (LPSTR)60);

   (*SHShutDownDialog)(0);

   FreeLibrary(hInst);

   } }

  

  問:在VC中有無方法可以像VFP一樣加減日期,從而得出它們之間的時間差值?

  

  答:可以使用CTime類來表示日期,如:

  CTime t1( 1999, 3, 19, 22, 15, 0 ); // 1999年3月19日22:15

  CTime t2( 1999, 3, 20, 22, 15, 0 ); // 1999年3月20日22:15

  CTimeSpan ts = t2 - t1;

  // 對兩個日期變量相減,差值保存在CTimeSpan變量中

  ASSERT( ts.GetTotalSeconds() == 86400L );




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