locked
Windows Mobile上是否有类似WM_DEVICECHANGE的消息? RRS feed

  • 问题

  • 我使用Vs2008, windows mobile 5.0 pocket PC SDK在一台WM5.0手机上进行开发。我的程序通过USB线与PC相连,借助ActiveSync同步数据。我现在希望当用户拔除USB线时,手机端的程序能捕获这个事件并自动退出。在PC上我可以使用WM_DEVICECHANGE获取USB插入和拔除的消息,但是在手机上注册WM_DEVICECHANGE的函数似乎不可用。

    我尝试使用ConnMgrRegisterForStatusChangeNotification来监听USB插拔的消息,但是并不总能收到拔除的消息。我也尝试了RequestDeviceNotifications,但是当手机上的USB线被拔除时,并没有收到消息。

    我该如何做呢?

     

    2011年8月11日 9:50

答案

  • 轮询注册表当然是个可行的方法,比如在程序开始时启动一个Timer,然后使用如下代码:

    BOOL IsUSBConnected(void) 
    { 
    	DWORD dwCradled = 0; 
    	RegistryGetDWORD(HKEY_LOCAL_MACHINE, TEXT("System\\State\\Hardware"), TEXT("Cradled"), &dwCradled); 
    	// 
    	if(dwCradled==1) 
    		return TRUE; 
    	else 
    		return FALSE; 
    }
    


    但是我不希望写这么个难看的轮询,我希望找找系统级的消息。我曾尝试RAPI的通知,但是没有找到合适的例子,因此没有成功。

     

    我也尝试了使用ConnMgrRegisterForStatusChangeNotification,首先注册这个消息

    	//注册监听USB设备插拔消息
    	g_nConnectPcMessage = ::RegisterWindowMessage(CONNMGR_STATUS_CHANGE_NOTIFICATION_MSG);
    	if (g_nConnectPcMessage == 0)
    	{
    		 return FALSE;
    	}
    	if(S_OK != ConnMgrRegisterForStatusChangeNotification(TRUE, hWnd))
    	{
    		return FALSE;
    	}
    

     

    然后在消息循环里接受它

    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
      int wmId, wmEvent;
      PAINTSTRUCT ps;
      HDC hdc;
    
      static SHACTIVATEINFO s_sai;
    
    	//利用前面注册的消息判断USB是否断开
    	if (g_nConnectPcMessage == message)
    	{
    		if (wParam == CONNMGR_STATUS_DISCONNECTED)
    		{
    			IsPcConnected(hWnd);
    		}
    	}
    
      //下面是普通的消息循环,略去
    }

    然后写个函数判断拔出的到底是不是USB,避免用户拔出了SD卡但是判断错误。这段代码基本是照抄MSDN。
    void IsPcConnected(HWND hWnd)
    
    {
    
    	CONNMGR_CONNECTION_DETAILED_STATUS *pStatus = NULL;
    
    	DWORD dwSize = 0;
    
    
    
    	//Query first time
    
    	HRESULT hr = ::ConnMgrQueryDetailedStatus(pStatus, &dwSize);
    
    	if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
    
    	{
    
    		//Re-malloc the buffer
    
    		pStatus = (CONNMGR_CONNECTION_DETAILED_STATUS *)new BYTE[dwSize];
    
    		if (!pStatus) return;
    
    
    
    		//retry queryment
    
    		hr = ::ConnMgrQueryDetailedStatus(pStatus, &dwSize);
    
    	}
    
    
    
    	BOOL bIsPcConnected = FALSE;
    
    
    
    	if (S_OK == hr)
    
    	{
    
    		CONNMGR_CONNECTION_DETAILED_STATUS *pNextStatus = pStatus;
    
    		for ( ; NULL != pNextStatus; pNextStatus = pNextStatus->pNext)
    
    		{
    
    			if (CM_CONNTYPE_PC == pNextStatus->dwType)
    
    			{
    
    				bIsPcConnected = TRUE;
    
    			}
    
    		}
    
    	}
    
    
    
    	if (FALSE == bIsPcConnected)
    
    	{
    
    		DestroyWindow(hWnd);
    
    	}
    
    
    
    	delete[] (pStatus);
    
    }
    
    




    2011年8月15日 2:11

全部回复

  • 你好,

    网上找了很久也没有找到已有的解决方法,不知道能否从注册表入手?

    在你找到答案以后,希望贴出来给大家共享下,谢谢!


    施炯
    2011年8月12日 8:51
    版主
  • 轮询注册表当然是个可行的方法,比如在程序开始时启动一个Timer,然后使用如下代码:

    BOOL IsUSBConnected(void) 
    { 
    	DWORD dwCradled = 0; 
    	RegistryGetDWORD(HKEY_LOCAL_MACHINE, TEXT("System\\State\\Hardware"), TEXT("Cradled"), &dwCradled); 
    	// 
    	if(dwCradled==1) 
    		return TRUE; 
    	else 
    		return FALSE; 
    }
    


    但是我不希望写这么个难看的轮询,我希望找找系统级的消息。我曾尝试RAPI的通知,但是没有找到合适的例子,因此没有成功。

     

    我也尝试了使用ConnMgrRegisterForStatusChangeNotification,首先注册这个消息

    	//注册监听USB设备插拔消息
    	g_nConnectPcMessage = ::RegisterWindowMessage(CONNMGR_STATUS_CHANGE_NOTIFICATION_MSG);
    	if (g_nConnectPcMessage == 0)
    	{
    		 return FALSE;
    	}
    	if(S_OK != ConnMgrRegisterForStatusChangeNotification(TRUE, hWnd))
    	{
    		return FALSE;
    	}
    

     

    然后在消息循环里接受它

    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
      int wmId, wmEvent;
      PAINTSTRUCT ps;
      HDC hdc;
    
      static SHACTIVATEINFO s_sai;
    
    	//利用前面注册的消息判断USB是否断开
    	if (g_nConnectPcMessage == message)
    	{
    		if (wParam == CONNMGR_STATUS_DISCONNECTED)
    		{
    			IsPcConnected(hWnd);
    		}
    	}
    
      //下面是普通的消息循环,略去
    }

    然后写个函数判断拔出的到底是不是USB,避免用户拔出了SD卡但是判断错误。这段代码基本是照抄MSDN。
    void IsPcConnected(HWND hWnd)
    
    {
    
    	CONNMGR_CONNECTION_DETAILED_STATUS *pStatus = NULL;
    
    	DWORD dwSize = 0;
    
    
    
    	//Query first time
    
    	HRESULT hr = ::ConnMgrQueryDetailedStatus(pStatus, &dwSize);
    
    	if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
    
    	{
    
    		//Re-malloc the buffer
    
    		pStatus = (CONNMGR_CONNECTION_DETAILED_STATUS *)new BYTE[dwSize];
    
    		if (!pStatus) return;
    
    
    
    		//retry queryment
    
    		hr = ::ConnMgrQueryDetailedStatus(pStatus, &dwSize);
    
    	}
    
    
    
    	BOOL bIsPcConnected = FALSE;
    
    
    
    	if (S_OK == hr)
    
    	{
    
    		CONNMGR_CONNECTION_DETAILED_STATUS *pNextStatus = pStatus;
    
    		for ( ; NULL != pNextStatus; pNextStatus = pNextStatus->pNext)
    
    		{
    
    			if (CM_CONNTYPE_PC == pNextStatus->dwType)
    
    			{
    
    				bIsPcConnected = TRUE;
    
    			}
    
    		}
    
    	}
    
    
    
    	if (FALSE == bIsPcConnected)
    
    	{
    
    		DestroyWindow(hWnd);
    
    	}
    
    
    
    	delete[] (pStatus);
    
    }
    
    




    2011年8月15日 2:11