soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
SNativeWnd.cpp
1#include <souistd.h>
3#include <core/SNativeWnd.h>
4
5SNSBEGIN
6
7#ifndef ENABLE_THUNK
8#ifdef _WIN32
9#define ENABLE_THUNK 1
10#else
11#define ENABLE_THUNK 0
12#endif //_WIN32
13#endif // ENABLE_THUNK
14
15//////////////////////////////////////////////////////////////////////////
16// thunk 技术实现参考http://www.cppblog.com/proguru/archive/2008/08/24/59831.html
17//////////////////////////////////////////////////////////////////////////
18
19#if defined(__i386__) || defined(__X86__) || defined(_M_IX86)
20#pragma pack(push, 1)
21struct tagThunk
22{
23 DWORD m_mov;
24 DWORD m_this;
25 BYTE m_jmp;
26 DWORD m_relproc;
27 void Init(DWORD_PTR proc, void *pThis)
28 {
29 m_mov = 0x042444C7;
30 m_this = (DWORD)(ULONG_PTR)pThis;
31 m_jmp = 0xe9;
32 m_relproc = (DWORD)((INT_PTR)proc - ((INT_PTR)this + sizeof(tagThunk)));
33 FlushInstructionCache(GetCurrentProcess(), this, sizeof(tagThunk));
34 }
35 void *GetCodeAddress()
36 {
37 return this;
38 }
39};
40#pragma pack(pop)
41#elif defined(_M_AMD64) || defined(__amd64__) || defined(__x86_64__)
42#if defined(__linux__)
43#pragma pack(push, 2)
44struct tagThunk
45{
46 USHORT RdiMov; // mov rdi, pThis
47 ULONG64 RdiImm; //
48 USHORT RaxMov; // mov rax, target
49 ULONG64 RaxImm; //
50 USHORT RaxJmp; // jmp target
51 void Init(DWORD_PTR proc, void *pThis)
52 {
53 RdiMov = 0xbf48; // mov rdi, pThis
54 RdiImm = (ULONG64)pThis; //
55 RaxMov = 0xb848; // mov rax, target
56 RaxImm = (ULONG64)proc; //
57 RaxJmp = 0xe0ff; // jmp rax
58 BOOL b = FlushInstructionCache(GetCurrentProcess(), this, sizeof(tagThunk));
59 }
60 // some thunks will dynamically allocate the memory for the code
61 void *GetCodeAddress()
62 {
63 return this;
64 }
65};
66#else //__linux__
67#pragma pack(push, 2)
68struct tagThunk
69{
70 USHORT RcxMov; // mov rcx, pThis
71 ULONG64 RcxImm; //
72 USHORT RaxMov; // mov rax, target
73 ULONG64 RaxImm; //
74 USHORT RaxJmp; // jmp target
75 void Init(DWORD_PTR proc, void *pThis)
76 {
77 RcxMov = 0xb948; // mov rcx, pThis
78 RcxImm = (ULONG64)pThis; //
79 RaxMov = 0xb848; // mov rax, target
80 RaxImm = (ULONG64)proc; //
81 RaxJmp = 0xe0ff; // jmp rax
82 FlushInstructionCache(GetCurrentProcess(), this, sizeof(tagThunk));
83 }
84 // some thunks will dynamically allocate the memory for the code
85 void *GetCodeAddress()
86 {
87 return this;
88 }
89};
90#pragma pack(pop)
91#endif //__linux__
92
93#elif defined(__arm__) || defined(_M_ARM)
94#pragma pack(push, 4)
95struct tagThunk // this should come out to 16 bytes
96{
97 DWORD m_mov_r0; // mov r0, pThis
98 DWORD m_mov_pc; // mov pc, pFunc
99 DWORD m_pThis;
100 DWORD m_pFunc;
101 void Init(DWORD_PTR proc, void *pThis)
102 {
103 m_mov_r0 = 0xE59F0000;
104 m_mov_pc = 0xE59FF000;
105 m_pThis = (DWORD)pThis;
106 m_pFunc = (DWORD)proc;
107 // write block from data cache and
108 // flush from instruction cache
109 FlushInstructionCache(GetCurrentProcess(), this, sizeof(tagThunk));
110 }
111 void *GetCodeAddress()
112 {
113 return this;
114 }
115};
116#pragma pack(pop)
117#elif defined(__arm64__) || defined(_M_ARM64) || defined(__aarch64__)
118#pragma pack(push, 1)
119struct tagThunk // this should come out to 16 bytes
120{
121 DWORD m_ldr_r16; // ldr x16, [pc, #24]
122 DWORD m_ldr_r0; // ldr x0, [pc, #12]
123 DWORD m_br; // br x16
124 DWORD m_pad;
125 ULONG64 m_pThis;
126 ULONG64 m_pFunc;
127
128 void Init(DWORD_PTR proc, void *pThis)
129 {
130 m_ldr_r16 = 0x580000D0;
131 m_ldr_r0 = 0x58000060;
132 m_br = 0xd61f0200;
133 m_pThis = (ULONG64)pThis;
134 m_pFunc = (ULONG64)proc;
135 // write block from data cache and
136 // flush from instruction cache
137 FlushInstructionCache(GetCurrentProcess(), this, sizeof(tagThunk));
138 }
139 void *GetCodeAddress()
140 {
141 return this;
142 }
143};
144#pragma pack(pop)
145#else
146#error Only AMD64, ARM, ARM64 and X86 supported
147#endif
148
149SNativeWndHelper::SNativeWndHelper()
150 : m_hInst(0)
151 , m_sharePtr(NULL)
152 , m_atom(0)
153{
154}
155
156BOOL SNativeWndHelper::Init(HINSTANCE hInst, LPCTSTR pszClassName, BOOL bImeApp)
157{
158 SAutoLock lock(m_cs);
159 if (m_hHeap)
160 return FALSE;
161 m_hInst = hInst;
162 m_hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
163 m_atom = SNativeWnd::RegisterSimpleWnd(m_hInst, pszClassName, bImeApp);
164 return TRUE;
165}
166
167SNativeWndHelper::~SNativeWndHelper()
168{
169 if (m_hHeap)
170 HeapDestroy(m_hHeap);
171 if (m_atom)
172 UnregisterClass((LPCTSTR)(UINT_PTR)m_atom, m_hInst);
173}
174
176{
177 m_cs.Enter();
178 m_sharePtr = p;
179}
180
182{
183 m_cs.Leave();
184}
185
186//////////////////////////////////////////////////////////////////////////
187SNativeWnd::SNativeWnd()
188 : m_bDestoryed(FALSE)
189 , m_pCurrentMsg(NULL)
190 , m_hWnd(0)
191 , m_pfnSuperWindowProc(::DefWindowProc)
192 , m_pThunk(NULL)
193{
194 m_msgHandlerInfo.fun = NULL;
195 m_msgHandlerInfo.ctx = NULL;
196}
197
198SNativeWnd::~SNativeWnd(void)
199{
200}
201
202ATOM SNativeWnd::RegisterSimpleWnd(HINSTANCE hInst, LPCTSTR pszSimpleWndName, BOOL bImeWnd)
203{
204 WNDCLASSEX wcex = { sizeof(WNDCLASSEX), 0 };
205 wcex.cbSize = sizeof(WNDCLASSEX);
206 wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | (bImeWnd ? CS_IME : 0);
207 wcex.lpfnWndProc = StartWindowProc; // ��һ����������
208 wcex.hInstance = hInst;
209 wcex.hCursor = ::LoadCursor(NULL, IDC_ARROW);
210 wcex.lpszClassName = pszSimpleWndName;
211 return ::RegisterClassEx(&wcex);
212}
213
214void SNativeWnd::InitWndClass(HINSTANCE hInst, LPCTSTR pszSimpleWndName, BOOL bImeWnd)
215{
216 SNativeWndHelper::instance()->Init(hInst, pszSimpleWndName, bImeWnd);
217}
218
219HWND SNativeWnd::CreateNative(LPCTSTR lpWindowName, DWORD dwStyle, DWORD dwExStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, int nID, LPVOID lpParam)
220{
222#if ENABLE_THUNK
223 m_pThunk = (tagThunk *)HeapAlloc(SNativeWndHelper::instance()->GetHeap(), HEAP_ZERO_MEMORY | HEAP_CREATE_ENABLE_EXECUTE, sizeof(tagThunk));
224#endif
225 HWND hWnd = ::CreateWindowEx(dwExStyle, (LPCTSTR)(UINT_PTR)SNativeWndHelper::instance()->GetSimpleWndAtom(), lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, (HMENU)(UINT_PTR)nID, SNativeWndHelper::instance()->GetAppInstance(), lpParam);
227#if ENABLE_THUNK
228 if (!hWnd)
229 {
230 HeapFree(SNativeWndHelper::instance()->GetHeap(), 0, m_pThunk);
231 m_pThunk = NULL;
232 }
233#endif
234 return hWnd;
235}
236
238{
239 return m_hWnd;
240}
241
243{
244#if ENABLE_THUNK
245 if (m_pThunk)
246 {
247 HeapFree(SNativeWndHelper::instance()->GetHeap(), 0, m_pThunk);
248 m_pThunk = NULL;
249 }
250#endif
251 m_hWnd = 0;
252}
253
254LRESULT CALLBACK SNativeWnd::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
255{
256#if ENABLE_THUNK
257 SNativeWnd *pThis = (SNativeWnd *)hWnd;
258#else
259 SNativeWnd *pThis = (SNativeWnd *)::GetWindowLongPtr(hWnd, GWLP_OPAQUE);
260#endif
261 MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam };
262 const MSG *pOldMsg = pThis->m_pCurrentMsg;
263 pThis->m_pCurrentMsg = &msg;
264 LRESULT lRes = 0;
265 if (pThis->m_msgHandlerInfo.fun)
266 {
267 BOOL bHandled = pThis->m_msgHandlerInfo.fun(&msg, &lRes, pThis->m_msgHandlerInfo.ctx);
268 if (bHandled)
269 return lRes;
270 }
271
272 // pass to the message map to process
273 BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
274 // restore saved value for the current message
275 SASSERT(pThis->m_pCurrentMsg == &msg);
276
277 // do the default processing if message was not handled
278 if (!bRet)
279 {
280 if (uMsg != WM_NCDESTROY)
281 lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
282 else
283 {
284 // unsubclass, if needed
285 LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
286 lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
287 if (pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
288 ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
289 // mark window as destryed
290 pThis->m_bDestoryed = TRUE;
291 }
292 }
293 if ((pThis->m_bDestoryed) && pOldMsg == NULL)
294 {
295 // clear out window handle
296 HWND hWndThis = pThis->m_hWnd;
297 pThis->m_hWnd = 0;
298 pThis->m_bDestoryed = FALSE;
299 // clean up after window is destroyed
300 pThis->m_pCurrentMsg = pOldMsg;
301 pThis->OnFinalMessage(hWndThis);
302 }
303 else
304 {
305 pThis->m_pCurrentMsg = pOldMsg;
306 }
307 return lRes;
308}
309
310LRESULT CALLBACK SNativeWnd::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
311{
312 SNativeWnd *pThis = (SNativeWnd *)SNativeWndHelper::instance()->GetSharePtr();
314 pThis->m_hWnd = hWnd;
315#if ENABLE_THUNK
316 // 初始化Thunk,做了两件事:1、mov指令替换hWnd为对象指针,2、jump指令跳转到WindowProc
317 pThis->m_pThunk->Init((DWORD_PTR)WindowProc, pThis);
318 // 得到Thunk指针
319 WNDPROC pProc = (WNDPROC)pThis->m_pThunk->GetCodeAddress();
320 // 调用下面的语句后,以后消息来了,都由pProc处理
321 ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
322 return pProc(hWnd, uMsg, wParam, lParam);
323#else
324 ::SetWindowLongPtr(hWnd, GWLP_OPAQUE, (ULONG_PTR)pThis);
325 ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (ULONG_PTR)WindowProc);
326 return WindowProc(hWnd, uMsg, wParam, lParam);
327#endif // ENABLE_THUNK
328}
329
331{
332 SASSERT(::IsWindow(hWnd));
333// Allocate the thunk structure here, where we can fail gracefully.
334#if ENABLE_THUNK
335 m_pThunk = (tagThunk *)HeapAlloc(SNativeWndHelper::instance()->GetHeap(), HEAP_ZERO_MEMORY | HEAP_CREATE_ENABLE_EXECUTE, sizeof(tagThunk));
336 m_pThunk->Init((DWORD_PTR)WindowProc, this);
337 WNDPROC pProc = (WNDPROC)m_pThunk->GetCodeAddress();
338#else
339 ::SetWindowLongPtr(hWnd, GWLP_OPAQUE, (LONG_PTR)this);
340 WNDPROC pProc = WindowProc;
341#endif
342 WNDPROC pfnWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
343 if (pfnWndProc == NULL)
344 {
345#if ENABLE_THUNK
346 HeapFree(SNativeWndHelper::instance()->GetHeap(), 0, m_pThunk);
347 m_pThunk = NULL;
348#endif
349 return FALSE;
350 }
351 m_pfnSuperWindowProc = pfnWndProc;
352 m_hWnd = hWnd;
353 return TRUE;
354}
355
356HWND SNativeWnd::UnsubclassWindow(BOOL bForce /*= FALSE*/)
357{
358 SASSERT(m_hWnd != 0);
359
360#if ENABLE_THUNK
361 WNDPROC pOurProc = (WNDPROC)m_pThunk->GetCodeAddress();
362#else
363 WNDPROC pOurProc = WindowProc;
364#endif
365 WNDPROC pActiveProc = (WNDPROC)::GetWindowLongPtr(m_hWnd, GWLP_WNDPROC);
366
367 HWND hWnd = 0;
368 if (bForce || pOurProc == pActiveProc)
369 {
370 if (!::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnSuperWindowProc))
371 return 0;
372#if ENABLE_THUNK == 0
373 ::SetWindowLongPtr(m_hWnd, GWLP_OPAQUE, (LONG_PTR)0);
374#endif // ENABLE_THUNK
376 hWnd = m_hWnd;
377 m_hWnd = 0;
378 }
379 return hWnd;
380}
381
382LRESULT SNativeWnd::ForwardNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
383{
384 LRESULT lResult = 0;
385 switch (uMsg)
386 {
387 case WM_COMMAND:
388 case WM_NOTIFY:
389 case WM_PARENTNOTIFY:
390 case WM_DRAWITEM:
391 case WM_MEASUREITEM:
392 case WM_COMPAREITEM:
393 case WM_DELETEITEM:
394 case WM_VKEYTOITEM:
395 case WM_CHARTOITEM:
396 case WM_HSCROLL:
397 case WM_VSCROLL:
398 bHandled = TRUE;
399 lResult = ::SendMessage(GetParent(), uMsg, wParam, lParam);
400 break;
401 default:
402 bHandled = FALSE;
403 break;
404 }
405 return lResult;
406}
407
408LRESULT SNativeWnd::ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
409{
410 HWND hWndChild = 0;
411
412 switch (uMsg)
413 {
414 case WM_COMMAND:
415 if (lParam != 0) // not from a menu
416 hWndChild = (HWND)lParam;
417 break;
418 case WM_NOTIFY:
419 hWndChild = ((LPNMHDR)lParam)->hwndFrom;
420 break;
421 case WM_PARENTNOTIFY:
422 switch (LOWORD(wParam))
423 {
424 case WM_CREATE:
425 case WM_DESTROY:
426 hWndChild = (HWND)lParam;
427 break;
428 default:
429 hWndChild = GetDlgItem(m_hWnd, HIWORD(wParam));
430 break;
431 }
432 break;
433 case WM_DRAWITEM:
434 if (wParam) // not from a menu
435 hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem;
436 break;
437 case WM_MEASUREITEM:
438 if (wParam) // not from a menu
439 hWndChild = GetDlgItem(m_hWnd, ((LPMEASUREITEMSTRUCT)lParam)->CtlID);
440 break;
441 case WM_COMPAREITEM:
442 if (wParam) // not from a menu
443 hWndChild = ((LPCOMPAREITEMSTRUCT)lParam)->hwndItem;
444 break;
445 case WM_DELETEITEM:
446 if (wParam) // not from a menu
447 hWndChild = ((LPDELETEITEMSTRUCT)lParam)->hwndItem;
448
449 break;
450 case WM_VKEYTOITEM:
451 case WM_CHARTOITEM:
452 case WM_HSCROLL:
453 case WM_VSCROLL:
454 hWndChild = (HWND)lParam;
455 break;
456#ifdef _WIN32
457 case WM_CTLCOLORBTN:
458 case WM_CTLCOLORDLG:
459 case WM_CTLCOLOREDIT:
460 case WM_CTLCOLORLISTBOX:
461 case WM_CTLCOLORMSGBOX:
462 case WM_CTLCOLORSCROLLBAR:
463 case WM_CTLCOLORSTATIC:
464 hWndChild = (HWND)lParam;
465 break;
466#endif //_WIN32
467 default:
468 break;
469 }
470
471 if (hWndChild == 0)
472 {
473 bHandled = FALSE;
474 return 1;
475 }
476 bHandled = TRUE;
477 SASSERT(::IsWindow(hWndChild));
478 return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam);
479}
480
481BOOL SNativeWnd::DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult)
482{
483 switch (uMsg)
484 {
485 case OCM_COMMAND:
486 case OCM_NOTIFY:
487 case OCM_PARENTNOTIFY:
488 case OCM_DRAWITEM:
489 case OCM_MEASUREITEM:
490 case OCM_COMPAREITEM:
491 case OCM_DELETEITEM:
492 case OCM_VKEYTOITEM:
493 case OCM_CHARTOITEM:
494 case OCM_HSCROLL:
495 case OCM_VSCROLL:
496#ifdef _WIN32
497 case OCM_CTLCOLORBTN:
498 case OCM_CTLCOLORDLG:
499 case OCM_CTLCOLOREDIT:
500 case OCM_CTLCOLORLISTBOX:
501 case OCM_CTLCOLORMSGBOX:
502 case OCM_CTLCOLORSCROLLBAR:
503 case OCM_CTLCOLORSTATIC:
504#endif //_WIN32
505 lResult = ::DefWindowProc(hWnd, uMsg - OCM__BASE, wParam, lParam);
506 return TRUE;
507 default:
508 break;
509 }
510 return FALSE;
511}
512
513LRESULT SNativeWnd::DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
514{
515 return ::CallWindowProc(m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam);
516}
517
519{
520 const MSG *pMsg = m_pCurrentMsg;
521 LRESULT lRes = 0;
522 if (pMsg != NULL)
523 lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
524 return lRes;
525}
526
527BOOL SNativeWnd::CenterWindow(HWND hWndCenter /*= NULL*/)
528{
529 SASSERT(::IsWindow(m_hWnd));
530
531 // determine owner window to center against
532 DWORD dwStyle = GetStyle();
533 if (hWndCenter == 0)
534 {
535 if (dwStyle & WS_CHILD)
536 hWndCenter = ::GetParent(m_hWnd);
537 else
538 hWndCenter = ::GetWindow(m_hWnd, GW_OWNER);
539
540 if (hWndCenter == 0)
541 {
542 hWndCenter = ::GetActiveWindow();
543 if (hWndCenter == m_hWnd)
544 hWndCenter = 0;
545 }
546 }
547
548 // get coordinates of the window relative to its parent
549 RECT rcDlg;
550 ::GetWindowRect(m_hWnd, &rcDlg);
551 RECT rcArea;
552 RECT rcCenter;
553 HWND hWndParent;
554 if (!(dwStyle & WS_CHILD))
555 {
556 // don't center against invisible or minimized windows
557 if (hWndCenter != 0)
558 {
559 DWORD dwStyleCenter = (DWORD)::GetWindowLongPtr(hWndCenter, GWL_STYLE);
560 if (!(dwStyleCenter & WS_VISIBLE) || (dwStyleCenter & WS_MINIMIZE))
561 hWndCenter = 0;
562 }
563
564 // center within screen coordinates
565#if WINVER < 0x0500
566 ::SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL);
567#else
568 HMONITOR hMonitor = 0;
569 if (hWndCenter != 0)
570 {
571 hMonitor = ::MonitorFromWindow(hWndCenter, MONITOR_DEFAULTTONEAREST);
572 }
573 else
574 {
575 hMonitor = ::MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
576 }
577
578 MONITORINFO minfo;
579 minfo.cbSize = sizeof(MONITORINFO);
580 ::GetMonitorInfo(hMonitor, &minfo);
581
582 rcArea = minfo.rcWork;
583#endif
584 if (hWndCenter == 0)
585 rcCenter = rcArea;
586 else
587 ::GetWindowRect(hWndCenter, &rcCenter);
588 }
589 else
590 {
591 // center within parent client coordinates
592 hWndParent = ::GetParent(m_hWnd);
593 SASSERT(::IsWindow(hWndParent));
594
595 ::GetClientRect(hWndParent, &rcArea);
596 SASSERT(::IsWindow(hWndCenter));
597 ::GetClientRect(hWndCenter, &rcCenter);
598 ::MapWindowPoints(hWndCenter, hWndParent, (POINT *)&rcCenter, 2);
599 }
600
601 int DlgWidth = rcDlg.right - rcDlg.left;
602 int DlgHeight = rcDlg.bottom - rcDlg.top;
603
604 // find dialog's upper left based on rcCenter
605 int xLeft = (rcCenter.left + rcCenter.right) / 2 - DlgWidth / 2;
606 int yTop = (rcCenter.top + rcCenter.bottom) / 2 - DlgHeight / 2;
607
608 // if the dialog is outside the screen, move it inside
609 if (xLeft + DlgWidth > rcArea.right)
610 xLeft = rcArea.right - DlgWidth;
611 if (xLeft < rcArea.left)
612 xLeft = rcArea.left;
613
614 if (yTop + DlgHeight > rcArea.bottom)
615 yTop = rcArea.bottom - DlgHeight;
616 if (yTop < rcArea.top)
617 yTop = rcArea.top;
618
619 // map screen coordinates to child coordinates
620 return ::SetWindowPos(m_hWnd, 0, xLeft, yTop, -1, -1, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
621}
622
623BOOL SNativeWnd::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags /*= 0*/)
624{
625 SASSERT(::IsWindow(m_hWnd));
626
627 DWORD dwStyle = (DWORD)::GetWindowLongPtr(m_hWnd, GWL_STYLE);
628 DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
629 if (dwStyle == dwNewStyle)
630 return FALSE;
631
632 ::SetWindowLongPtr(m_hWnd, GWL_STYLE, dwNewStyle);
633 if (nFlags != 0)
634 {
635 ::SetWindowPos(m_hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
636 }
637
638 return TRUE;
639}
640
641BOOL SNativeWnd::ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags /*= 0*/)
642{
643 // todo:hjx to support ws_ex_composite change during running.
644 SASSERT(::IsWindow(m_hWnd));
645
646 DWORD dwStyle = (DWORD)::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE);
647 DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
648 if (dwStyle == dwNewStyle)
649 return FALSE;
650
651 ::SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, dwNewStyle);
652 if (nFlags != 0)
653 {
654 ::SetWindowPos(m_hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
655 }
656
657 return TRUE;
658}
659
660BOOL SNativeWnd::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD dwMsgMapID /*= 0*/)
661{
662 return FALSE;
663}
664
665BOOL SNativeWnd::UpdateLayeredWindow(HDC hdcDst, POINT *pptDst, SIZE *psize, HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend, DWORD dwFlags)
666{
667 SASSERT(::IsWindow(m_hWnd));
668#ifdef _WIN32
669 return ::UpdateLayeredWindow(m_hWnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
670#else
671 return FALSE;
672#endif //_WIN32
673}
674
675BOOL SNativeWnd::SetLayeredWindowAttributes(COLORREF crKey, BYTE bAlpha, DWORD dwFlags)
676{
677 SASSERT(::IsWindow(m_hWnd));
678 return ::SetLayeredWindowAttributes(m_hWnd, crKey, bAlpha, dwFlags);
679}
680
681int SNativeWnd::SetWindowRgn(HRGN hRgn, BOOL bRedraw /*=TRUE*/)
682{
683 SASSERT(::IsWindow(m_hWnd));
684 return ::SetWindowRgn(m_hWnd, hRgn, bRedraw);
685}
686
687BOOL SNativeWnd::ShowWindow(int nCmdShow)
688{
689 SASSERT(::IsWindow(m_hWnd));
690 return ::ShowWindow(m_hWnd, nCmdShow);
691}
692
693BOOL SNativeWnd::MoveWindow2(LPCRECT lpRect, BOOL bRepaint /*= TRUE*/)
694{
695 SASSERT(::IsWindow(m_hWnd));
696 return ::MoveWindow(m_hWnd, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, bRepaint);
697}
698
699BOOL SNativeWnd::MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint /*= TRUE*/)
700{
701 SASSERT(::IsWindow(m_hWnd));
702 return ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint);
703}
704
706{
707 SASSERT(::IsWindow(m_hWnd));
708 return ::IsWindowVisible(m_hWnd);
709}
710
712{
713 SASSERT(::IsWindow(m_hWnd));
714 return ::IsZoomed(m_hWnd);
715}
716
718{
719 SASSERT(::IsWindow(m_hWnd));
720 return ::IsIconic(m_hWnd);
721}
722
723int SNativeWnd::GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) const
724{
725 SASSERT(::IsWindow(m_hWnd));
726 return ::GetWindowText(m_hWnd, lpszStringBuf, nMaxCount);
727}
728
729BOOL SNativeWnd::SetWindowText(LPCTSTR lpszString)
730{
731 SASSERT(::IsWindow(m_hWnd));
732 return ::SetWindowText(m_hWnd, lpszString);
733}
734
735BOOL SNativeWnd::SendNotifyMessage(UINT message, WPARAM wParam /*= 0*/, LPARAM lParam /*= 0*/)
736{
737 SASSERT(::IsWindow(m_hWnd));
738 return ::SendNotifyMessage(m_hWnd, message, wParam, lParam);
739}
740
741BOOL SNativeWnd::PostMessage(UINT message, WPARAM wParam /*= 0*/, LPARAM lParam /*= 0*/)
742{
743 SASSERT(::IsWindow(m_hWnd));
744 return ::PostMessage(m_hWnd, message, wParam, lParam);
745}
746
747LRESULT SNativeWnd::SendMessage(UINT message, WPARAM wParam /*= 0*/, LPARAM lParam /*= 0*/)
748{
749 SASSERT(::IsWindow(m_hWnd));
750 return ::SendMessage(m_hWnd, message, wParam, lParam);
751}
752
754{
755 SASSERT(::IsWindow(m_hWnd));
756 return ::SetFocus(m_hWnd);
757}
758
760{
761 SASSERT(::IsWindow(m_hWnd));
762 return ::SetCapture(m_hWnd);
763}
764
766{
767 return ::GetCapture();
768}
769
771{
772 return ::ReleaseCapture();
773}
774
776{
777 SASSERT(::IsWindow(m_hWnd));
778 return ::ShowCaret(m_hWnd);
779}
780
782{
783 SASSERT(::IsWindow(m_hWnd));
784 return ::HideCaret(m_hWnd);
785}
786
787BOOL SNativeWnd::CreateCaret(HBITMAP hBitmap, int nWidth, int nHeight)
788{
789 SASSERT(::IsWindow(m_hWnd));
790 return ::CreateCaret(m_hWnd, hBitmap, nWidth, nHeight);
791}
792
794{
795 SASSERT(::IsWindow(m_hWnd));
796 return ::ReleaseDC(m_hWnd, hDC);
797}
798
800{
801 SASSERT(::IsWindow(m_hWnd));
802 return ::GetWindowDC(m_hWnd);
803}
804
806{
807 SASSERT(::IsWindow(m_hWnd));
808 return ::GetDC(m_hWnd);
809}
810
811BOOL SNativeWnd::KillTimer(UINT_PTR nIDEvent)
812{
813 SASSERT(::IsWindow(m_hWnd));
814 return ::KillTimer(m_hWnd, nIDEvent);
815}
816
817UINT_PTR SNativeWnd::SetTimer(UINT_PTR nIDEvent, UINT nElapse, void(CALLBACK *lpfnTimer)(HWND, UINT, UINT_PTR, DWORD) /*= NULL*/)
818{
819 SASSERT(::IsWindow(m_hWnd));
820 return ::SetTimer(m_hWnd, nIDEvent, nElapse, (TIMERPROC)lpfnTimer);
821}
822
823int SNativeWnd::MapWindowRect(HWND hWndTo, LPRECT lpRect) const
824{
825 SASSERT(::IsWindow(m_hWnd));
826 return ::MapWindowPoints(m_hWnd, hWndTo, (LPPOINT)lpRect, 2);
827}
828
829int SNativeWnd::MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) const
830{
831 SASSERT(::IsWindow(m_hWnd));
832 return ::MapWindowPoints(m_hWnd, hWndTo, lpPoint, nCount);
833}
834
835BOOL SNativeWnd::ScreenToClient2(LPRECT lpRect) const
836{
837 SASSERT(::IsWindow(m_hWnd));
838 if (!::ScreenToClient(m_hWnd, (LPPOINT)lpRect))
839 return FALSE;
840 return ::ScreenToClient(m_hWnd, ((LPPOINT)lpRect) + 1);
841}
842
843BOOL SNativeWnd::ScreenToClient(LPPOINT lpPoint) const
844{
845 SASSERT(::IsWindow(m_hWnd));
846 return ::ScreenToClient(m_hWnd, lpPoint);
847}
848
849BOOL SNativeWnd::ClientToScreen2(LPRECT lpRect) const
850{
851 SASSERT(::IsWindow(m_hWnd));
852 if (!::ClientToScreen(m_hWnd, (LPPOINT)lpRect))
853 return FALSE;
854 return ::ClientToScreen(m_hWnd, ((LPPOINT)lpRect) + 1);
855}
856
857BOOL SNativeWnd::ClientToScreen(LPPOINT lpPoint) const
858{
859 SASSERT(::IsWindow(m_hWnd));
860 return ::ClientToScreen(m_hWnd, lpPoint);
861}
862
863BOOL SNativeWnd::GetClientRect(LPRECT lpRect) const
864{
865 SASSERT(::IsWindow(m_hWnd));
866 return ::GetClientRect(m_hWnd, lpRect);
867}
868
869BOOL SNativeWnd::GetWindowRect(LPRECT lpRect) const
870{
871 SASSERT(::IsWindow(m_hWnd));
872 return ::GetWindowRect(m_hWnd, lpRect);
873}
874
875BOOL SNativeWnd::InvalidateRect(LPCRECT lpRect, BOOL bErase /*= TRUE*/)
876{
877 SASSERT(::IsWindow(m_hWnd));
878 return ::InvalidateRect(m_hWnd, lpRect, bErase);
879}
880
881BOOL SNativeWnd::Invalidate(BOOL bErase /*= TRUE*/)
882{
883 SASSERT(::IsWindow(m_hWnd));
884 return ::InvalidateRect(m_hWnd, NULL, bErase);
885}
886
888{
889 return ::IsWindow(m_hWnd);
890}
891
893{
894 SASSERT(::IsWindow(m_hWnd));
895 return ::DestroyWindow(m_hWnd);
896}
897
898BOOL SNativeWnd::SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags)
899{
900 SASSERT(::IsWindow(m_hWnd));
901 return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, nFlags);
902}
903
905{
906 SASSERT(::IsWindow(m_hWnd));
907 return ::IsWindowEnabled(m_hWnd);
908}
909
910HWND SNativeWnd::SetParent(HWND hWndNewParent)
911{
912 SASSERT(::IsWindow(m_hWnd));
913 return ::SetParent(m_hWnd, hWndNewParent);
914}
915
917{
918 SASSERT(::IsWindow(m_hWnd));
919 return ::GetParent(m_hWnd);
920}
921
922LONG_PTR SNativeWnd::SetWindowLongPtr(int nIndex, LONG_PTR dwNewLong)
923{
924 SASSERT(::IsWindow(m_hWnd));
925 return ::SetWindowLongPtr(m_hWnd, nIndex, dwNewLong);
926}
927
928LONG_PTR SNativeWnd::GetWindowLongPtr(int nIndex) const
929{
930 SASSERT(::IsWindow(m_hWnd));
931 return ::GetWindowLongPtr(m_hWnd, nIndex);
932}
933
935{
936 SASSERT(::IsWindow(m_hWnd));
937 return (DWORD)::GetWindowLongPtr(m_hWnd, GWL_EXSTYLE);
938}
939
941{
942 SASSERT(::IsWindow(m_hWnd));
943 return (DWORD)::GetWindowLongPtr(m_hWnd, GWL_STYLE);
944}
945
947{
948 SASSERT(::IsWindow(m_hWnd));
949 return ::GetDlgCtrlID(m_hWnd);
950}
951
953{
954 return m_pCurrentMsg;
955}
956
957void SNativeWnd::SetMsgHandler(THIS_ FunMsgHandler fun, void *ctx)
958{
959 m_msgHandlerInfo.fun = fun;
960 m_msgHandlerInfo.ctx = ctx;
961}
962
967
968SNSEND
Header file for SCriticalSection and SAutoLock classes.
Interface and Implementation for Native Window Handling.
Auto-lock class for managing critical sections.
static SNativeWndHelper * instance()
Retrieves the singleton instance of SNativeWndHelper.
Definition SNativeWnd.h:100
void UnlockSharePtr()
Unlocks a shared pointer.
BOOL Init(HINSTANCE hInst, LPCTSTR pszClassName, BOOL bImeApp)
Initializes the helper with the application instance and window class name.
void LockSharePtr(void *p)
Locks a shared pointer.
BOOL IsIconic() SCONST OVERRIDE
Checks if the window is iconic (minimized).
BOOL IsZoomed() SCONST OVERRIDE
Checks if the window is zoomed (maximized).
BOOL ClientToScreen2(LPRECT lpRect) SCONST OVERRIDE
Converts client rectangle coordinates to screen coordinates.
BOOL ScreenToClient(LPPOINT lpPoint) SCONST OVERRIDE
Converts screen coordinates to client coordinates.
static void InitWndClass(HINSTANCE hInst, LPCTSTR pszSimpleWndName, BOOL bImeWnd)
Initializes the window class.
int SetWindowRgn(HRGN hRgn, BOOL bRedraw=TRUE) OVERRIDE
Sets the window region.
int MapWindowRect(HWND hWndTo, LPRECT lpRect) SCONST OVERRIDE
Maps a rectangle from one window to another.
HDC GetDC() OVERRIDE
Retrieves a device context for the window.
const MSG * m_pCurrentMsg
Pointer to the current message.
Definition SNativeWnd.h:739
HWND SetCapture() OVERRIDE
Sets the window to capture the mouse.
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Window procedure callback function.
BOOL GetWindowRect(LPRECT lpRect) SCONST OVERRIDE
Retrieves the window rectangle.
LRESULT ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Reflects notifications to the appropriate handler.
HWND GetCapture() OVERRIDE
Retrieves the handle to the window that has captured the mouse.
BOOL ReleaseCapture() OVERRIDE
Releases the mouse capture.
int MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) SCONST OVERRIDE
Maps points from one window to another.
BOOL SetLayeredWindowAttributes(COLORREF crKey, BYTE bAlpha, DWORD dwFlags) OVERRIDE
Sets the layered window attributes.
BOOL IsWindowVisible() SCONST OVERRIDE
Checks if the window is visible.
BOOL Invalidate(BOOL bErase=TRUE) OVERRIDE
Invalidates the entire window.
BOOL IsWindow() SCONST OVERRIDE
Checks if the handle is a valid window handle.
BOOL IsWindowEnabled() SCONST OVERRIDE
Checks if the window is enabled.
LRESULT SendMessage(UINT message, WPARAM wParam=0, LPARAM lParam=0) OVERRIDE
Sends a message to the window.
const MSG * GetCurrentMessage() SCONST OVERRIDE
Retrieves the current message being processed.
void SetMsgHandler(FunMsgHandler fun, void *ctx) OVERRIDE
Sets the message handler for the window.
BOOL MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint=TRUE) OVERRIDE
Moves the window to the specified position and resizes it.
tagThunk * m_pThunk
Thunk structure.
Definition SNativeWnd.h:768
BOOL SendNotifyMessage(UINT message, WPARAM wParam=0, LPARAM lParam=0) OVERRIDE
Sends a notify message to the window.
LRESULT ForwardNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Forwards notifications to the appropriate handler.
WNDPROC m_pfnSuperWindowProc
Pointer to the superclass window procedure.
Definition SNativeWnd.h:769
UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT nElapse, void(CALLBACK *lpfnTimer)(HWND, UINT, UINT_PTR, DWORD)=NULL) OVERRIDE
Sets a timer for the window.
HWND UnsubclassWindow(BOOL bForce=FALSE) OVERRIDE
Unsubclasses a window.
BOOL ShowCaret() OVERRIDE
Shows the caret.
MsgHandlerInfo m_msgHandlerInfo
Message handler information.
Definition SNativeWnd.h:741
static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Start window procedure callback function (executed once).
BOOL SubclassWindow(HWND hWnd) OVERRIDE
Subclasses an existing window.
BOOL PostMessage(UINT message, WPARAM wParam=0, LPARAM lParam=0) OVERRIDE
Posts a message to the window.
DWORD GetStyle() SCONST OVERRIDE
Retrieves the window style.
HWND GetParent() OVERRIDE
Retrieves the handle to the parent window.
HWND SetFocus() OVERRIDE
Sets the input focus to the window.
DWORD GetExStyle() SCONST OVERRIDE
Retrieves the extended window style.
virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD dwMsgMapID=0)
Processes a window message.
HWND SetParent(HWND hWndNewParent) OVERRIDE
Sets the handle to the parent window.
BOOL SetWindowText(LPCTSTR lpszString) OVERRIDE
Sets the window text.
BOOL m_bDestoryed
Flag indicating if the window is destroyed.
Definition SNativeWnd.h:740
BOOL ClientToScreen(LPPOINT lpPoint) SCONST OVERRIDE
Converts client coordinates to screen coordinates.
static ATOM RegisterSimpleWnd(HINSTANCE hInst, LPCTSTR pszSimpleWndName, BOOL bImeWnd)
Registers a simple window class.
BOOL ShowWindow(int nCmdShow) OVERRIDE
Sets the show state of the window.
BOOL KillTimer(UINT_PTR nIDEvent) OVERRIDE
Kills a timer for the window.
HWND m_hWnd
Handle to the window.
Definition SNativeWnd.h:744
int GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) SCONST OVERRIDE
Retrieves the window text.
BOOL CreateCaret(HBITMAP hBitmap, int nWidth, int nHeight) OVERRIDE
Creates a caret for the window.
LONG_PTR SetWindowLongPtr(int nIndex, LONG_PTR dwNewLong) OVERRIDE
Sets the long pointer value at the specified index.
BOOL CenterWindow(HWND hWndCenter=0) OVERRIDE
Centers the window relative to another window.
BOOL GetClientRect(LPRECT lpRect) SCONST OVERRIDE
Retrieves the client rectangle.
BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags=0) OVERRIDE
Modifies the window style.
HDC GetWindowDC() OVERRIDE
Retrieves a device context for the entire window.
HWND CreateNative(LPCTSTR lpWindowName, DWORD dwStyle, DWORD dwExStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, int nID=0, LPVOID lpParam=0) OVERRIDE
Creates a native window.
static BOOL DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult)
Default reflection handler for notifications.
BOOL ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags=0) OVERRIDE
Modifies the extended window style.
BOOL SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags) OVERRIDE
Sets the window position.
HWND GetHwnd() OVERRIDE
Retrieves the handle to the window.
virtual void OnFinalMessage(HWND hWnd)
Handles the final message for the window.
int ReleaseDC(HDC hDC) OVERRIDE
Releases a device context.
BOOL HideCaret() OVERRIDE
Hides the caret.
BOOL ScreenToClient2(LPRECT lpRect) SCONST OVERRIDE
Converts screen rectangle coordinates to client coordinates.
int GetDlgCtrlID() SCONST OVERRIDE
Retrieves the dialog control ID.
MsgHandlerInfo * GetMsgHandler() OVERRIDE
Retrieves the message handler for the window.
LONG_PTR GetWindowLongPtr(int nIndex) SCONST OVERRIDE
Retrieves the long pointer value at the specified index.
BOOL UpdateLayeredWindow(HDC hdcDst, POINT *pptDst, SIZE *psize, HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend, DWORD dwFlags) OVERRIDE
Updates the layered window.
LRESULT DefWindowProc()
Calls the default window procedure.
BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase=TRUE) OVERRIDE
Invalidates a specified rectangle of the window.
BOOL DestroyWindow() OVERRIDE
Destroys the window.
BOOL MoveWindow2(LPCRECT lpRect, BOOL bRepaint=TRUE) OVERRIDE
Moves the window to the specified position and resizes it using a rectangle.
Structure containing message handler information.