查看: 2120|回复: 0
打印 上一主题 下一主题

unity3d 实现windows 消息

[复制链接]

435

主题

2

听众

6371

积分

高级设计师

Rank: 6Rank: 6

纳金币
6372
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2012-9-13 11:39:32 |只看该作者 |倒序浏览
先前提到可以用 Hooks 的方法在 Unity 裡監控 Windows Message,但是使用 Hooks 這個方法我們沒辦法更改 Message 的內容。因此這邊提出第二個方式。Windows 傳送 Message 給 Unity 時,會呼叫 Unity 預設的 Message 處理函數,但透過函數:



pOldWndProc =(WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC, (LONG)SubWndProc);



我們可以將原本 Windows 呼叫 Unity 預設的 Message 處理函數改為呼叫我們指定的函數,指定的函數把我們想要處理的 Message 處理完,再把剩下的 Message 丟回給 Unity 來處理。



原本實作是使用 dllimport 讓 SetWindowLong function 可以在 C# 裡呼叫, 並把整個 callback function 及流程實作出來,且測試時運作都相當正常,但程式在關閉時會出現 Access Violation 的錯誤,後來將整個實作改成 C DLL 之後錯誤才沒有出現,不知道是什麼原因?底下是 DLL 部分的原始碼:



#include "stdafx.h"


LRESULT CALLBACK SubWndProc(
HWND hWnd,
UINT nMessage,
WPARAM wParam, LPARAM lParam);

WNDPROC  gOldWndProc = NULL;
HWND  gUnityWnd = NULL;

#ifdef    __cplusplus
extern "C" {
#endif    /*    __cplusplus    */

__declspec(dllexport) bool __stdcall init(HWND hWnd)
{
  gOldWndProc =(WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC, (LONG)SubWndProc);
  gUnityWnd =hWnd;

  if (gOldWndProc !=NULL)
   return ***e;

  return false;
}

__declspec(dllexport) void __stdcall release()
{
  SetWindowLong(gUnityWnd, GWL_WNDPROC, (LONG)gOldWndProc);
  gOldWndProc =0;
  gUnityWnd =0;
}

#ifdef    __cplusplus
}
#endif    /*    __cplusplus    */


LRESULT CALLBACK SubWndProc(
HWND hWnd,
UINT nMessage,
WPARAM wParam, LPARAM lParam)
{
switch(nMessage)
{
  case WM_IME_SETCONTEXT:
  case WM_IME_STARTCOMPOSITION:
  case WM_IME_ENDCOMPOSITION:
  case WM_IME_COMPOSITION:
  case WM_IME_REQUEST:
   {
    //...
   }
   break;
}
return CallWindowProc(gOldWndProc, hWnd, nMessage, wParam, lParam);
}


Unity 可以透過呼叫 DLL 提供的 init() 函數,讓 Windows 改為呼叫我們指定的函數 (SubWndProc) 來處理 Message,透過 release() 函數讓 Message 處理流程復原。底下是 Unity 部分的原始碼(DLL 檔名為 UnityIMEDLL.dll 且檔案放在 Assets/Plugins 目錄下)

using UnityEngine;

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Interopservices;

public class IMEInputBox : MonoBehaviour
{
    //-----------------------------------------------------------
    [DllImport("UnityIMEDLL")]
    protected static extern bool init(IntPtr hWnd);

    [DllImport("UnityIMEDLL")]
    protected static extern void release();

    [DllImport("user32")]
    protected static extern IntPtr GetActiveWindow();

    //-----------------------------------------------------------
// Use this for initialization
void Start ()
{
        Debug.Log("init UnityIMEDLL.");
        try
        {
            init(GetActiveWindow());
        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }
}

    void OnDisable()
    {
        Debug.Log("release UnityIMEDLL.");
        try
        {
            release();
        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }
    }
}

分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2024-11-18 02:27 , Processed in 0.105072 second(s), 33 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部