VC6.0 常見問題處理

1、VC++6.0無法設置斷點:先關閉程序,然後刪除目錄下的.opt和.ncb文件,重新打開項目,就OK!


2、這個無奈問題折騰了很久,一直以爲是數據庫問題,本來是修改的東西,害我把數據庫整體變成了access的:vc++如何利用ADO在連接sql2005

m_pConnection->Open("Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=HRMS;Data Source=.\\SQLEXPRESS","","",adModeUnknown); //建立數據庫連接,Data Source不需要完整路徑,但是儘量添加,防止出錯

Provider=SQLOLEDB.1 ------打開數據庫用oledb的方式連接
Integrated Security=SSPI
  Microsoft安全支持提供器接口(SSPI)是定義得較全面的公用API,用來獲得驗證、信息完整性、信息隱私等集成安全服務,以及用於所有分佈式應用程序協議的安全方面的服務。應用程序協議設計者能夠利用該接口獲得不同的安全性服務而不必修改協議本身。上面這句話的意思就是這個連接採用了這個接口,如果沒有定義就會出錯!
Persist Security Info ----是否保存安全信息
User ID-------------------用戶名
PassWord------------------密碼
Initial Catalog-----------數據庫的名稱或者數據庫ip或者目錄
Data Source---------------數據源

[DBNETLIB][ConnectionOpen(connect()).]SQL Server 不存在或拒絕訪問的解決辦法:這個問題基本上是連接數據庫的連接字出錯,網上天馬行空的還是跳過吧!

更爲詳細的VC+ADO下連接並操作sql2005數據庫方法總結操作請參考:http://topic.csdn.net/u/20111028/14/186567e7-e9a2-4ee8-8eb6-5604d4ebd9db.html,至此,數據庫部分:ado,odbc來操作sql/access告一段落。


3、MFC類成員函數作爲線程函數的解決辦法

int  dwThreadId;    HANDLE hTread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc1,this,0,(LPDWORD)&dwThreadId);

//(LPTHREAD_START_ROUTINE)如果不加的話出現如下問題(其實說來說去就是不符合createthread各個參數的類型,保險起見都強制類型轉換,如此函數最後一個參數(LPDWORD)&dwThreadId)

error C2664: 'CreateThread' : cannot convert parameter 3 from 'unsigned long (void *)' to 'unsigned long (__stdcall *)(void *)

正常的成員函數不能作爲線程函數!這時候怎麼辦呢?~可以把要作爲線程函數的成員函數定義成static的,如
public:
         static DWORD WINAPI globalConverterFunc(LPVOID lp);
這樣,編譯可以通過!但是問題又來了,static成員不能操作非static成員變量,就是沒有this指針~解決辦法是,建立線程時,傳遞一個this指針就啦~如:
HANDLE hThread;
	DWORD ThreadID;
	hThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)globalConverterFunc,this,0,&ThreadID);
這樣,在static線程函數裏面,做個強制類型轉換,把lp轉換成類指針,問題解決!
自己在寫程序中是這麼做的:
聲明:static DWORD WINAPI ReadPortThread(LPVOID lpParameter);
調用:HANDLE m_hReadThread=CreateThread(NULL,0,ReadPortThread,this,0,NULL);
多線程函數部分:
DWORD WINAPI CSerialPorts::ReadPortThread(LPVOID lpParameter)
{
    CSerialPorts* m_pSerial=(CSerialPorts*)lpParameter;    //把lpParameter轉換成類指針
    CThreadDlg* m_Thread=new CThreadDlg();                 //在CSerialPorts的多線程下調用CThreadDlg類中的函數
    ....................
    m_Thread->DataArrivedMsg(buf,dwLength);
}
LPVOID是一個沒有類型的指針,也就是說你可以將任意類型的指針賦值給LPVOID類型的變量(一般作爲參數傳遞),然後在使用的時候再轉換回來。  
可以將其理解爲long型的指針,指向void型。 

4、int num = 10;char str[100]; itoa(num, str, 2);       itoa的頭文件是<stdlib.h>,因此keil或者c中都是可以用的!

itoa()函數有3個參數:第一個參數是要轉換的數字,第二個參數是目標字符串,第三個參數是轉移數字時所用 的基數。在上例中,轉換基數爲10。10:十進制;2:二進制……
//             m_Show=num;        //更新edit控件數據的方法之一
//             UpdateData(FALSE);//將成員變量的數據傳給界面 而UpdateData(TRUE);的話是將界面數據傳給成員變量


5、ASSERT(m_nTimer != 0);如果m_nTimer!=0返回非0繼續運行,如果0則顯示錯誤內容,但不會終止程序運行,如果想顯示錯誤並終止運行使用

VERIFY( booleanExpression)


6、vs2008中char []' to 'LPCTSTR'報錯:

m_Show.SetWindowText("你好");如果上述報錯,在項目(project)->屬性(property)中常規(general)中有個字符集選項,裏面有選用多字節還是Unicode改成多字節(Multi-Byte),問題解決。


7、再現離奇問題,EVC工程,當然VC6也可能出現:

0120514\Mfc\Src\dlgcore.cpp(1006) : error C2491: 'CDialog::classCDialog' : ……幾十號錯誤,都是因爲莫名在工程中的資源中添加了dlgcore.cpp,把他刪掉即可。


8、MFC幾個常用的消息映射

    工具欄的載入OnCreate函數是“消息”中的WM_CREATE消息映射的;

    定時器使用OnTimer函數是“消息”中的WM_TIMER消息映射的;

    OnInitDialog是在"重寫"中的OnInitDialog消息映射的;

    其他:windows消息常見的有鼠標消息(如WM_LBUTTONDOWN)消息)、鍵盤字符消息(WM_CHAR消息)、鍵盤按鍵消息(WM_KEYDOWN)、窗口重畫消息WM_PAINT,水平和垂直條滾動消息WM_HSCROLL和WM_VSCROLL)以及系統時鐘消息WM_TIMER等。


9、mfc基於對話框的應用程序如何添加菜單欄:在對話框頭文件中聲明CMenu 變量,例如CMenu m_Menu;在OnInitDlg()中加入如下語句:m_Menu.LoadMenu("此處加入你的菜單id");SetMenu(&m_Menu);


10、線程問題:error C3867: ...function call missing argument list=====

    hRecvThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)CommRecvTread,this,0,NULL);其中CommRecvTread聲明一定要加上static如下static DWORD CommRecvTread(LPVOID pParam);——個人理解,線程是全局跑的,如果你所有的線程都在一個類下當然可以不加static但如果有其他類,則必須加保證其全局性。


11、 CreateEvent講解

事件對象就像一個開關:它只有兩種狀態---開和關。當一個事件處於”開”狀態,我們稱其爲”有信號”否則稱爲”無信號”。可以在一個線程的執行函數中創建一個事件對象,然後觀察它的狀態,如果是”無信號”就讓該線程睡眠,這樣該線程佔用的CPU時間就比較少。

產生事件對象的函數如下:  

HANDLE     CreateEvent(

        LPSECURITY_ATTRIBUTES     lpEventAttributes,     //     SD   
        BOOL     bManualReset,                                                 //     reset     type   
        BOOL     bInitialState,                                                      //     initial     state   
        LPCTSTR     lpName                                                       //     object     name   
    );   
    該函數創建一個Event同步對象,如果CreateEvent調用成功的話,會返回新生成的對象的句柄,否則返回NULL。

參數說明:
    lpEventAttributes     一般爲NULL   
    bManualReset              創建的Event是自動復位還是人工復位.如果true,人工復位,  一旦該Event被設置爲有信號,則它一直會等到ResetEvent()API被調用時纔會恢復 爲無信號.    如果爲false,Event被設置爲有信號,則當有一個wait到它的Thread時,  該Event就會自動復位,變成無信號.   如果想在每次調用WaitForSingleObject後讓WINDOWS爲您自動地把事件地狀態恢復爲”無信號”狀態,必須把該參數設爲FALSE,否則,您必須每次調用ResetEvent函數來清除事件的信號。
    bInitialState             初始狀態,true,有信號,false無信號   
    lpName                  事件對象的名稱。您在OpenEvent函數中可能使用。

註釋:
   一個Event被創建以後,可以用OpenEvent()API來獲得它的Handle,用CloseHandle()   來關閉它,用SetEvent()或PulseEvent()來設置它使其有信號,用ResetEvent()      來使其無信號,用WaitForSingleObject()或WaitForMultipleObjects()來等待其變爲有信號.  
    PulseEvent()是一個比較有意思的使用方法,正如這個API的名字,它使一個Event 對象的狀態發生一次脈衝變化,從無信號變成有信號再變成無信號,而整個操作是原子的.   

    對自動復位的Event對象,它僅釋放第一個等到該事件的thread(如果有),而對於人工復位的Event對象,它釋放所有等待的thread.  


12、Visual C++開發調試技巧

如何清除所有的斷點Ctrl + Shift + F9

如何檢測程序中的括號是否匹配Ctrl + ]

添加Lib文件到當前工程單擊菜單【Project】->【Settings…】彈出“Project Setting”對話框,切換到“Link”標籤頁,在“Object/library modules”處輸入Lib文件名稱,不同的Lib之間用空格格開;

變量設定:線程函數可以且必須是全局函數或者是靜態成員函數;

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