wndhook.cpp
上传用户:kittypts
上传日期:2018-02-11
资源大小:241k
文件大小:8k
源码类别:

PlugIns编程

开发平台:

Visual C++

  1. /*****************************************************************************
  2. Windows Live Messenger Plugin Demo
  3. Copyright (C) 2008  Hern醤 Di Pietro
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program.  If not, see <http://www.gnu.org/licenses/>.
  14. /*****************************************************************************/
  15. #include "wlmplugin.h"
  16. #include "Oleacc.h"
  17. #include "initguid.h"
  18. #include "cinfownd.h"
  19. #include "aboutdlg.h"
  20. #include "clrzwind.h"
  21. // ---------------------------------------------------------------------------
  22. // If an accessibility object contains a name that matches the WLM contact
  23. // format (we assume ends with < mail_address >) it returns the contact ID
  24. // (actually *this is* the email address)
  25. //
  26. // returns FALSE if the source string does not conform 
  27. // 
  28. static BOOL AccObjToContactID(const WCHAR* wszAccName, WCHAR* wszContactId)
  29. {
  30. int cAtChars = 0; // number of @ chars
  31. const WCHAR* wszBegin = wszAccName;
  32. if (wszAccName == NULL) return FALSE;
  33. wszAccName += wcslen(wszAccName)-1;  // advance towards end
  34. if (*wszAccName == '>')
  35. {
  36. // search backwards until '<', count @
  37. while (*wszAccName-- != '<' && wszBegin != wszAccName )
  38. if (*wszAccName == '@') cAtChars++;
  39. // invalid -- this is not an accessibility object for a contact
  40. if (wszAccName == wszBegin || cAtChars > 1)
  41. return FALSE;
  42. else
  43. {
  44. // copy ID without < >
  45. wcscpy_s (wszContactId, MAXSTRL, wszAccName+2);
  46. wszContactId[wcslen(wszContactId)-1] = '';
  47. return TRUE;
  48. }
  49. }
  50. else
  51. return FALSE;
  52. };
  53. // Callback function that handles MS Accessibility events
  54. //
  55. void CALLBACK HandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd, 
  56.  LONG idObject, LONG idChild, 
  57.  DWORD dwEventThread, DWORD dwmsEventTime)
  58. {
  59. IAccessible* pIAcc = 0;
  60. MSNMessenger::IMSNMessengerContact* pIMsnContact = 0;
  61. VARIANT varChild, varRole, varState;
  62. BSTR name = NULL;
  63. WCHAR wszID[MAXSTRL];
  64. VariantInit(&varChild);
  65. HRESULT hr = AccessibleObjectFromEvent (hwnd, idObject, idChild, &pIAcc, &varChild);
  66. if ((hr == S_OK) && (pIAcc != NULL)) 
  67. {
  68. if (pIAcc->get_accName(varChild, &name) != S_FALSE)
  69. {
  70. switch (event)
  71. {
  72. case EVENT_OBJECT_FOCUS:
  73. // process only if the contact info window menu option is enabled
  74. if (AccObjToContactID(name, wszID) && g_wlmTopWindow.fEnableInfoWnd)
  75. {
  76. BSTR bstrID = SysAllocString(wszID);
  77. IDispatch* pIDisp;
  78. hr = g_wlmIfaces.pIMsn->raw_GetContact(bstrID, g_wlmIfaces.pIMsn->MyServiceId, &pIDisp);
  79. if (SUCCEEDED(hr))
  80. {
  81. if (SUCCEEDED(pIDisp->QueryInterface(MSNMessenger::IID_IMSNMessengerContact, 
  82. (void**)&pIMsnContact)))
  83. {
  84. ShowWindow(g_wlmContactInfoWindow.hwnd, SW_SHOWNA);
  85. // force window to repaint with new values
  86. g_wlmContactInfoWindow.wszContactID = bstrID;
  87. g_wlmContactInfoWindow.wszFriendlyName = pIMsnContact->FriendlyName;
  88. g_wlmContactInfoWindow.msStatus = pIMsnContact->Status;
  89. g_wlmContactInfoWindow.fBlocked = pIMsnContact->Blocked;
  90. g_wlmContactInfoWindow.fCanPage = pIMsnContact->CanPage;
  91. g_wlmContactInfoWindow.wszHomePhone 
  92. = pIMsnContact->GetPhoneNumber(MSNMessenger::MPHONE_TYPE_HOME);
  93. g_wlmContactInfoWindow.wszWorkPhone
  94. = pIMsnContact->GetPhoneNumber(MSNMessenger::MPHONE_TYPE_WORK);
  95. g_wlmContactInfoWindow.wszMobilePhone
  96. = pIMsnContact->GetPhoneNumber(MSNMessenger::MPHONE_TYPE_MOBILE);
  97. SendMessage(g_wlmContactInfoWindow.hwnd, WM_UPDATEBASECOLOR, 0, 0);
  98. pIMsnContact->Release();
  99. }
  100. pIDisp->Release();
  101. }
  102. SysFreeString(bstrID);
  103. }
  104. else // if it's focused to a non-contact element...
  105. {
  106. // Hide contact info window
  107. ShowWindow(g_wlmContactInfoWindow.hwnd, SW_HIDE);
  108. }
  109. break;
  110. case EVENT_OBJECT_STATECHANGE:
  111. // We handle this for toolbar buttons going to "pressed" state
  112. varRole.vt = VT_I4;
  113. pIAcc->get_accRole(varChild, &varRole);
  114. pIAcc->get_accState(varChild, &varState);
  115. if (varRole.lVal == ROLE_SYSTEM_BUTTONMENU)
  116. {
  117. if (varState.lVal == STATE_SYSTEM_PRESSED)
  118. // Execute action related to this button name
  119. g_actDisp.ExecuteAction(std::wstring(name), NULL);
  120. }
  121. break;
  122. }
  123. SysFreeString(name);
  124. }
  125. pIAcc->Release();
  126. }
  127. VariantClear(&varChild);
  128. }
  129. void Handle_CreateWindowExW (NktHandlerParams * hp)
  130. {
  131. // Check if it's creating WLM top level window
  132. // Warning! window class parameter can be interpreted as a pointer-to-string 
  133. // or as an atom. Atoms high-word are always zero
  134. LPCWSTR lpszWndClass = *(LPCWSTR*) PARAMETER_INDEX(1);
  135. if (lpszWndClass && HIWORD((INT_PTR )lpszWndClass) )
  136. if (wcscmp(lpszWndClass, g_wlmTopWindow.szWndClass) == 0)
  137. {
  138. g_wlmTopWindow.hwnd = (HWND)hp->context.regs->EAX;
  139. // Subclass window to process messages the way we want...
  140. g_wlmTopWindow.pfnOldWndProc = (WNDPROC) GetWindowLongPtr (g_wlmTopWindow.hwnd, GWLP_WNDPROC);
  141. SetWindowLongPtr (g_wlmTopWindow.hwnd, GWLP_WNDPROC, (LONG_PTR)WlmWndProc);
  142. }
  143. }
  144. // ---------------------------------------------------------------------------
  145. // sub classed top-level window procedure
  146. LRESULT CALLBACK WlmWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  147. {
  148. static HMENU hMainMenu;
  149. static HMENU hDemoMenu1;
  150. RECT r;
  151. bool fDone  = false;
  152. switch (uMsg)
  153. {
  154. case WM_SHOWWINDOW:
  155. hMainMenu = GetMenu(hwnd);
  156. hDemoMenu1 = CreatePopupMenu();
  157. AppendMenu(hMainMenu, MF_STRING | MF_POPUP, (UINT_PTR) hDemoMenu1, L"W&lmPluginDLL");
  158. AppendMenu(hDemoMenu1, MF_STRING, ID_MENU_DISPLAY_CONTACTINFO, L"Display Contact Information &Window");
  159. AppendMenu(hDemoMenu1, MF_STRING, ID_MENU_DEMO_ABOUT, L"&About...");
  160. DrawMenuBar(hwnd);
  161. case WM_COMMAND:
  162. // check if it's from our menu
  163. if (HIWORD(wParam) == 0)
  164. {
  165. switch (LOWORD(wParam))
  166. {
  167. case ID_MENU_DEMO_ABOUT:
  168. {
  169. SendMessage(g_hwndNktAbout, WM_UPDATEBASECOLOR, 0, 0);
  170. SendMessage(g_hwndNktAbout, WM_CREATECHILDCTRLS, 0, 0);
  171. GetWindowRect(g_hwndNktAbout, &r);
  172. SetWindowPos(g_hwndNktAbout, HWND_TOP,  (GetSystemMetrics(SM_CXSCREEN) / 2) - (r.right/2),
  173. (GetSystemMetrics(SM_CYSCREEN) / 2) - (r.bottom/2) , 0, 0, SWP_NOSIZE);
  174. AnimateWindow(g_hwndNktAbout, 300, AW_BLEND | AW_ACTIVATE);
  175. InvalidateRect(g_hwndNktAbout, NULL, FALSE); 
  176. break;
  177. }
  178. case ID_MENU_DISPLAY_CONTACTINFO:
  179. g_wlmTopWindow.fEnableInfoWnd = ~g_wlmTopWindow.fEnableInfoWnd;
  180. CheckMenuItem(hDemoMenu1, ID_MENU_DISPLAY_CONTACTINFO, 
  181. g_wlmTopWindow.fEnableInfoWnd ? MF_CHECKED : MF_UNCHECKED);
  182. break;
  183. }
  184. }
  185. break;
  186. case WM_MOVE:
  187. // change the contact info window position along this (if it's present)
  188. RECT r;
  189. POINT ptTopLeft;
  190. GetClientRect(hwnd, &r);
  191. ptTopLeft.x = r.left;
  192. ptTopLeft.y = r.top;
  193. ClientToScreen(hwnd, &ptTopLeft);
  194. MoveWindow (g_wlmContactInfoWindow.hwnd, ptTopLeft.x - CIW_DEFAULT_WIDTH - 10, 
  195. ptTopLeft.y, CIW_DEFAULT_WIDTH, CIW_DEFAULT_HEIGHT, TRUE);
  196. break;
  197. }
  198. return CallWindowProc(g_wlmTopWindow.pfnOldWndProc, hwnd, uMsg, wParam, lParam);
  199. }