Incoming call view custom of Windows Mobile PhoneCanvas
关于WinMobile电话自定义, 在SDK Documents里已经有说明 "Phone Canvas Customization"
位置: Shell, GWES, and User Interface > Shell > Shell OS Design Development >
Sample Code: ../WM650/PUBLIC/APPS/OAK/SAMPLES
1. Customizing Controls in the Phone Canvas
Shell > Shell OS Design Development > Phone Canvas Customization >
添加注册表, 告诉MSFT的程序说我们要自定义电话, 并说明要加载哪个DLL文件.
2. PHExtGetPhoneViewInfo 函数. 通过它, 可以调用自己自定义的对话框,
Shell > Shell OS Design Development > Phone Canvas Customization > 这里有说明哪些电话对框可以充许自定义 |
下面关于PHExtGetPhoneViewInfo的例子:
/*PHExtGetPhoneViewInfo Used to provide a new layout for the dialog box representing the phone view specified in parameter "view". Not all views support this functionality. See the below table. Either PH_VIF_SQUARE, PH_VIF_PORTRAIT, or PH_VIF_LANDSCAPE will be set in the pvif member indicating the dialog template that the phone application is requesting. To specify a dialog template, fill in the phInstance parameter and the plpTemplateName. phInstance identifies a module that contains a dialog box template named by the plpTemplateName parameter. plpTemplateName is a long pointer to a null-terminated string that names the dialog box template resource in the module identified by the phInstance parameter. This template is substituted for the phone application抯 dialog box template used to create the phone view. For numbered dialog box resources, plpTemplateName can be a value returned by the MAKEINTRESOURCE macro. Additionally, the OEM can provide a plpfnHook hook procedure in the phone view. The hook procedure can process messages sent to the dialog box representing the phone view. To enable a hook procedure, add the PH_VIF_ENABLEHOOK flag to the pvif parameter and specify the address of the hook procedure in the plpfnHook parameter. The hook procedure should return TRUE to indicate that the phone application should not process this message. A return value of FALSE will cause the phone application to continue with its default handling of the message. Note that if controls are added and/or removed, their control ids should not coincide with the same id's used in the default layouts. The phone dialogs may attempt to communicate with these controls via their control id. This function is called by the phone application both when phone view is being created and when the phone view needs to rotate due to a screen orientation change. This allows the phone application to use different dialog templates for portrait and landscape. Table: PH_VIEW_INCOMING // template : incoming call view PH_VIEW_DIALER // template : PocketPC dialer view PH_VIEW_CALL_PICKER // template : remove a call from a conference (GSM only) PH_VIEW_NETWORK_SELECTION // template : manual network selection (GSM only) PH_VIEW_CALL_HISTORY // NA (for PocketPC only, bitmaps can be changed) PH_VIEW_SPEED_DIAL // NA (for PocketPC only, bitmaps can be changed) PH_VIEW_SIM_PIN, // NA (for PocketPC only, bitmaps can be changed) PH_VIEW_PROGRESS // template : call progress or active calls view [in] view : Any of the PH_VIEW enums. It indicates which view the phone application is creating or rotating. Call history, speed dial, and the unlock SIM PIN views are not replaceable by the OEM. Hence, the phone application will not call PHExtGetPhoneViewInfo for these views. [in/out] pvif : PH_VIF_SQUARE, PH_VIF_PORTRAIT, and PH_VIF_LANDSCAPE are set as input. The client can add PH_VIF_ENABLEHOOK to indicate that plpfnHook is valid. [out] phInstance : see above. [out] plpTemplateName : See above. [out] plpfnHook : See above. returns: S_OK : success. E_NOTIMPL : the phone application should use its defaults.*/ extern "C" HRESULT PHExtGetPhoneViewInfo(PH_VIEW view, HINSTANCE* phInstance, PH_VIEWINFOFLAGS* pvif, LPPHONEVIEWHOOKPROC* plpfnHook, LPCTSTR* plpTemplateName) { HRESULT hr = E_NOTIMPL; // Specify dialog templates for dialer view switch (view) { // dialer view case PH_VIEW_DIALER: break; // progress view case PH_VIEW_PROGRESS: break; // incoming call view case PH_VIEW_INCOMING: switch(*pvif) { case PH_VIF_PORTRAIT: // Specify a calert portrait view dialog template *phInstance = g_MainWnd.m_hInst; *pvif = (PH_VIEWINFOFLAGS) (*pvif | PH_VIF_ENABLEHOOK); //如果不想HOOK的话,这行和下面那一行可以注释掉 *plpfnHook = (LPPHONEVIEWHOOKPROC)CalertWndProc; //如果不想HOOK的话,本行和上面那一行可以注释掉 *plpTemplateName = MAKEINTRESOURCE(dwIDD_CALERT_PORT); hr = S_OK; break; case PH_VIF_LANDSCAPE: // Specify a calert landscape view dialog template *phInstance = g_MainWnd.m_hInst; *pvif = (PH_VIEWINFOFLAGS) (*pvif | PH_VIF_ENABLEHOOK); *plpfnHook = (LPPHONEVIEWHOOKPROC)CalertWndProc; *plpTemplateName = MAKEINTRESOURCE(dwIDD_CALERT_LAND); hr = S_OK; break; default: break; } break; default: break; } return hr; }
这样当有电话进来的时候, 就会调用CalertWndProc, 和调用dwIDD_CALERT_XXX资源对话框了. 我做的是整个来电对话框自己Draw上相关的来电信息,还有接听/挂断按钮,添加菜单等. 没用dwIDD_CALERT_XXX资源对话框, 所以没有试过不用HOOK, 只换Caler资源对框来自定义的情况, 不过文档上说是可以的...
3. 来电时会调用CalertWndProc, 这里要添加一些小小的处理. 这个CallBack里的hWnd是最底层的(用Remote SPY 可以看得到), 所以要用两次GetParent来取得MSFT显示的来电对话框的handle, 将其它Move出显示区域,并对它进行SetWindowLong.
/********************************************************************* CalertWndProc Purpose: The windows procedure for the Calert control Arguments: HWND hWnd - handle to the window UINT uMsg - the message to process WPARAM wParam - additional parameter LPARAM lParam - additional parameter Returns: LRESULT lRes 0 = success **********************************************************************/ LRESULT CALLBACK CalertWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT lRes = 0; HWND hWndWorker = NULL; switch (uMsg) { case WM_INITDIALOG: m_hWndCalert = hWnd; // to hide and SetWindowLong the MSFT incoming call view main dialog hWndWorker = GetParent(hWnd); if (hWndWorker == NULL) { break; } m_hWndIncomingCall = GetParent(hWndWorker); if (m_hWndIncomingCall != NULL) { // 这里我将MSFT的来电对话框Move出去, 这样它就不会显示出来了 MoveWindow(m_hWndIncomingCall, -1, -1, 0, 0, FALSE); // set window long for MSFT incoming call view main dialog if (m_OldIncomingCallWndProc == NULL) { // 调用SetWindowLong, 来到来电对话框的CallBack消息. m_OldIncomingCallWndProc = (WNDPROC)SetWindowLong(m_hWndIncomingCall, GWL_WNDPROC, (LONG)IncomingCallWndProc); if(!m_OldIncomingCallWndProc) { DEBUGMSG(1 , (L"m_OldIncomingCallWndProc == NULL")); } } } break; default: break; } return lRes; }
4. IncomingCallWndProc 处理. SHBM_SHOW(用Remote SPY 可以看得到)这个就是来电BubbleBox, Show/Hide时的消息
/********************************************************************* IncomingCallWndProc Purpose: The windows procedure for the Incoming Call control Arguments: HWND hWnd - handle to the window UINT uMsg - the message to process WPARAM wParam - additional parameter LPARAM lParam - additional parameter Returns: LRESULT lRes 0 = success, else callback default **********************************************************************/ LRESULT CALLBACK CCalert::IncomingCallWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT lRet = S_OK; switch (uMsg) { case SHBM_SHOW: // shbox.h: Show/Hide dialog box. wParam == TRUE to Show. wParam == FALSE to Hide. lParam=TRUE to set foreground. if (wParam) { // 来电对话框 Show // 这里用来添加自 } // Hide the incoming call dialog box else { // hide the custome incoming call and the default incoming call // 来电对话框 Hide } break; default: return CallWindowProc(m_OldIncomingCallWndProc, hWnd, uMsg, wParam, lParam); break; } return lRet; }
上面第3步和第4步是之前自己跟出来, 但这样做会有问题. 就是设置PIN码锁之后, 无法显示来电对话框.
还是因为文档没查仔细的原因, 其实MSFT里文档已经有custom来电的处理方法了. 这样上面的第3,第4步就可以合为以下:
New 3. 通过Phone Canvas Messages来处理
Shell OS Design Development > Phone Canvas Customization > Phone Canvas Reference >
/* The following code example demonstrates how to use the WM_PH_ALERT_BEGIN message to redirect an incoming call alert to a custom UI that will display even when a device lock is enabled. In the example, the incoming call alert window is invoked upon receiving the WM_PH_ALERT_BEGIN message and returns TRUE to suppress the Microsoft incoming call alert UI. */ // // Incoming Alert Hook procedure that will be called. // // The following code example demonstrates how to use the WM_PH_ALERT_BEGIN message to redirect an incoming call alert to // a custom UI that will display even when a device lock is enabled. In the example, the incoming call alert window is invoked // upon receiving the WM_PH_ALERT_BEGIN message and returns TRUE to suppress the Microsoft incoming call alert UI. // // Incoming Alert Hook procedure that will be called. // BOOL CALLBACK IncomingAlertHookProc(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp) { switch (uMsg) { case WM_PH_ALERT_BEGIN: { if(HandleIncomingAlertBegin()) { // Return TRUE here to indicate to MSFT's code that we are handing the alert. return TRUE; } break; } case WM_PH_ALERT_END: { // hide the alert window if (g_hIncoming != NULL) { SetWindowPos(g_hIncoming, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_HIDEWINDOW); } // should return FALSE here to allow handing of ring tones break; } case WM_PH_ALERT_UPDATE: break; case WM_PH_ALERT_QUIT: break; case WM_PH_ALERT_RING: break; default: break; } return FALSE; }
不过调用自己的来电时, CreateWindow的话要注意
m_hWnd = CreateWindowEx(WS_EX_ABOVESTARTUP | WS_EX_TOPMOST /*| WS_EX_TOOLWINDOW*/, szWindowClass, NULL, WS_VISIBLE | WS_NONAVDONEBUTTON, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
如果Window已经Create过了,就要SetWindowPos一下
SetWindowPos(m_hWnd, HWND_TOPMOST, 0, g_MainWnd.m_nTaskBarHeight, nCxScreen, nCyScreen-2*g_MainWnd.m_nTaskBarHeight, SWP_STARTUP | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW); SetWindowPos(m_hWndMenuBar, HWND_TOPMOST, 0, nCyScreen-g_MainWnd.m_nTaskBarHeight, nCxScreen, g_MainWnd.m_nTaskBarHeight, SWP_STARTUP | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
好了, 这样当锁住的时候, 来电同样也可以弹出来了 :-<
OK, 这样当来电的时候就显示自定义的窗口了...
关于来电防火墙的处理嘛,就应该更简单了:-<
关于来电话定义的东西比较多, 这里我先写点对来电对话框自定义显示的小结, 等有时间再写其它的.
发表于 @ 2009年12月31日 09:43:00 | 评论( 5 ) | 举报| 收藏