2013-05-23

[MFC] 使用自訂的Cursor



1.將想要加入的Cursor(.cur檔)加入專案中
2.在類別下的MemberData中加入一個HCURSOR類別的成員(在此使用的名稱為 m_hNoDrop)

   protected:
      HCURSOR m_hNoDrop;

3.在類別建構子中加入以下指令

   m_hNoDrop = AfxGetApp()->LoadCursor( IDC_NODROP );

    註:IDC_NODROP為欲加入的cursor ID
4.在欲改變指標的區段加入

  SetCursor( m_hNoDrop  );

5.建立事件OnSetCursor:功能表中的View\MFC ClassWizard下,Object IDs選擇專案名稱,Messages選擇WM_SETCURSOR再選擇Add Function即可。

   BOOL Your_Project_Name::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
   {
      // TODO: Add your message handler code here and/or call default
      return true;
   }

註:1.須使該事件的回傳值為ture
     2.Your_Project_Name為您的專案名稱

[Qt]如何避免Qt所寫的dll被帶有參數的呼叫時造成的crash?

假設我們有一個由Qt所寫成的DLL, 當中有一個StartServer是這樣定義的:
extern "C"  MY_EXPORT  void  CALLBACK *StartServer(char* pcAddress, unsigned short uiPort, char* pcWorkingPath)
{
    if(g_pNewClass != NULL)
    {
        g_pNewClass->Start(pcAddress, uiPort, pcWorkingPath);
    }
    else
    {
        WriteDebug("g_pNewClass is NULL");
    }
    return g_pNewClass;
}
上述的CALLBACK很關鍵!!

2.而我們一般要呼叫dll的方式如下(以vc6為例):

 typedef void (CALLBACK* START)(char* , unsigned short , char* );
 START start = NULL;              
 start = (START)GetProcAddress(m_hMod, "StartServer");
 if(start == NULL)
 {
  //載入函數位置失敗
  TRACE("start not found");
 }
 else
 {
  start(m_pAddr, m_port,m_pWP);
 }


於是我們就會發現函數的位置無法取得,用Dependency Walker這套萬惡的工具一看DLL的內容才知道,
原來是Qt自己把函數的名字改掉了.

[名稱被改成了StartServer@12]



所以我們也要在GetProcAddress時將名字改成DLL內部所記載的:

start = (START)GetProcAddress(m_hMod, "StartServer@12");

如此一來就可以正確的傳值呼叫我們想要使用的函數啦!

[Qt]如何讓Qt建置的dll給其他語言使用

1.將 qtwinmigrate 安裝到Qt的目錄下


2.參照以下連結"windows下如何使用QT编写dll程序"進行設置


3.在dllMain前面加上敘述字MY_EXPORT以避免Qt把函數名稱改掉

#ifdef Q_WS_WIN
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT
#endif
extern "C" MY_EXPORT BOOL WINAPI DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpvReserved )
{
    ...
}


4.這樣就可以讓其他語言所撰寫的執行檔正常呼叫囉!


key words: QMfcApp, qtwinmigrate, dllMain, C++