Revert unwanted change
[reactos.git] / base / shell / rshell / CMenuDeskBar.cpp
1 /*
2 * Shell Menu Desk Bar
3 *
4 * Copyright 2014 David Quintana
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20 #include "precomp.h"
21 #include <atlwin.h>
22 #include <shlwapi_undoc.h>
23
24 #include "CMenuDeskBar.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(CMenuDeskBar);
27
28 const static GUID CGID_MenuDeskBar = { 0x5C9F0A12, 0x959E, 0x11D0, { 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x08, 0x26, 0x36 } };
29
30 extern "C"
31 HRESULT WINAPI CMenuDeskBar_Constructor(REFIID riid, LPVOID *ppv)
32 {
33 return ShellObjectCreator<CMenuDeskBar>(riid, ppv);
34 }
35
36 CMenuDeskBar::CMenuDeskBar() :
37 m_Client(NULL),
38 m_ClientWindow(NULL),
39 m_IconSize(0),
40 m_Banner(NULL),
41 m_Shown(FALSE),
42 m_ShowFlags(0)
43 {
44 }
45
46 CMenuDeskBar::~CMenuDeskBar()
47 {
48 }
49
50 LRESULT CMenuDeskBar::_OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
51 {
52 this->AddRef();
53
54 bHandled = FALSE;
55 return 0;
56 }
57
58 void CMenuDeskBar::OnFinalMessage(HWND /* hWnd */)
59 {
60 }
61
62 HRESULT STDMETHODCALLTYPE CMenuDeskBar::Initialize(THIS)
63 {
64 return S_OK;
65 }
66
67 HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetWindow(HWND *lphwnd)
68 {
69 if (lphwnd == NULL)
70 return E_POINTER;
71 *lphwnd = m_hWnd;
72 return S_OK;
73 }
74
75 HRESULT STDMETHODCALLTYPE CMenuDeskBar::ContextSensitiveHelp(BOOL fEnterMode)
76 {
77 return E_NOTIMPL;
78 }
79
80 HRESULT STDMETHODCALLTYPE CMenuDeskBar::OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus)
81 {
82 CComPtr<IInputObjectSite> ios;
83
84 HRESULT hr = m_Client->QueryInterface(IID_PPV_ARG(IInputObjectSite, &ios));
85 if (FAILED_UNEXPECTEDLY(hr))
86 return hr;
87
88 return ios->OnFocusChangeIS(punkObj, fSetFocus);
89 }
90
91 HRESULT STDMETHODCALLTYPE CMenuDeskBar::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds,
92 OLECMD prgCmds [], OLECMDTEXT *pCmdText)
93 {
94 return E_NOTIMPL;
95 }
96
97 HRESULT STDMETHODCALLTYPE CMenuDeskBar::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
98 DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
99 {
100 if (IsEqualIID(*pguidCmdGroup, CGID_MenuDeskBar))
101 {
102 switch (nCmdID)
103 {
104 case 2: // refresh
105 return S_OK;
106 case 3: // load complete
107 return S_OK;
108 case 4: // set font metrics
109 return S_OK;
110 }
111 }
112 if (IsEqualIID(*pguidCmdGroup, CGID_Explorer))
113 {
114 }
115 else if (IsEqualIID(*pguidCmdGroup, IID_IDeskBarClient))
116 {
117 switch (nCmdID)
118 {
119 case 0:
120 // hide current band
121 break;
122 case 2:
123 break;
124 case 3:
125 break;
126 }
127 }
128 return E_NOTIMPL;
129 }
130
131 HRESULT STDMETHODCALLTYPE CMenuDeskBar::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
132 {
133 HRESULT hr;
134
135 if (IsEqualGUID(guidService, SID_SMenuPopup) ||
136 IsEqualGUID(guidService, SID_SMenuBandParent) ||
137 IsEqualGUID(guidService, SID_STopLevelBrowser))
138 {
139 hr = this->QueryInterface(riid, ppvObject);
140 if (SUCCEEDED(hr))
141 return hr;
142 }
143
144 if (IsEqualGUID(guidService, SID_SMenuBandBottom) ||
145 IsEqualGUID(guidService, SID_SMenuBandBottomSelected) ||
146 IsEqualGUID(guidService, SID_SMenuBandChild))
147 {
148 if (m_Client == NULL)
149 return E_NOINTERFACE;
150
151 hr = IUnknown_QueryService(m_Client, guidService, riid, ppvObject);
152 if (SUCCEEDED(hr))
153 return hr;
154 }
155
156
157 if (m_Site == NULL)
158 return E_NOINTERFACE;
159
160 return IUnknown_QueryService(m_Site, guidService, riid, ppvObject);
161 }
162
163 HRESULT STDMETHODCALLTYPE CMenuDeskBar::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
164 {
165 return IUnknown_UIActivateIO(m_Client, fActivate, lpMsg);
166 }
167
168 HRESULT STDMETHODCALLTYPE CMenuDeskBar::HasFocusIO()
169 {
170 CComPtr<IInputObject> io;
171
172 HRESULT hr = m_Client->QueryInterface(IID_PPV_ARG(IInputObject, &io));
173 if (FAILED_UNEXPECTEDLY(hr))
174 return hr;
175
176 return io->HasFocusIO();
177 }
178
179 HRESULT STDMETHODCALLTYPE CMenuDeskBar::TranslateAcceleratorIO(LPMSG lpMsg)
180 {
181 CComPtr<IInputObject> io;
182
183 HRESULT hr = m_Client->QueryInterface(IID_PPV_ARG(IInputObject, &io));
184 if (FAILED_UNEXPECTEDLY(hr))
185 return hr;
186
187 return io->TranslateAcceleratorIO(lpMsg);
188 }
189
190 HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetClient(IUnknown *punkClient)
191 {
192 CComPtr<IDeskBarClient> pDeskBandClient;
193 HRESULT hr;
194
195 if (m_Client)
196 {
197 hr = m_Client->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pDeskBandClient));
198 if (FAILED_UNEXPECTEDLY(hr))
199 return hr;
200
201 pDeskBandClient->SetDeskBarSite(NULL);
202
203 pDeskBandClient = NULL;
204 m_Client = NULL;
205 }
206
207 if (punkClient == NULL)
208 return S_OK;
209
210 if (m_hWnd == NULL)
211 {
212 Create(NULL);
213 }
214
215 hr = punkClient->QueryInterface(IID_PPV_ARG(IUnknown, &m_Client));
216 if (FAILED_UNEXPECTEDLY(hr))
217 return hr;
218
219 hr = m_Client->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pDeskBandClient));
220 if (FAILED_UNEXPECTEDLY(hr))
221 return hr;
222
223 hr = pDeskBandClient->SetDeskBarSite(static_cast<IDeskBar*>(this));
224 if (FAILED_UNEXPECTEDLY(hr))
225 return hr;
226
227 return IUnknown_GetWindow(m_Client, &m_ClientWindow);
228 }
229
230 HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetClient(IUnknown **ppunkClient)
231 {
232 if (ppunkClient == NULL)
233 return E_POINTER;
234
235 if (!m_Client)
236 return E_FAIL;
237
238 return m_Client->QueryInterface(IID_PPV_ARG(IUnknown, ppunkClient));
239 }
240
241 HRESULT STDMETHODCALLTYPE CMenuDeskBar::OnPosRectChangeDB(LPRECT prc)
242 {
243 if (prc == NULL)
244 return E_POINTER;
245
246 return S_OK;
247 }
248
249 HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetSite(IUnknown *pUnkSite)
250 {
251 // Windows closes the bar if this is called when the bar is shown
252
253 if (m_Shown)
254 _CloseBar();
255
256 m_SubMenuParent = NULL;
257
258 m_Site = pUnkSite;
259
260 if (m_Site)
261 {
262 IUnknown_QueryService(m_Site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup, &m_SubMenuParent));
263 }
264 else
265 {
266 SetClient(NULL);
267 DestroyWindow();
268 }
269
270 return S_OK;
271 }
272
273 HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetSite(REFIID riid, void **ppvSite)
274 {
275 if (m_Site == NULL)
276 return E_FAIL;
277
278 return m_Site->QueryInterface(riid, ppvSite);
279 }
280
281 HRESULT STDMETHODCALLTYPE CMenuDeskBar::Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags)
282 {
283 HRESULT hr;
284 CComPtr<IOleCommandTarget> oct;
285 CComPtr<IInputObject> io;
286 CComPtr<IDeskBand> band;
287 CComPtr<IDeskBarClient> dbc;
288
289 if (m_hWnd == NULL)
290 return E_FAIL;
291
292 hr = IUnknown_QueryService(m_Client, SID_SMenuBandChild, IID_PPV_ARG(IOleCommandTarget, &oct));
293 if (FAILED_UNEXPECTEDLY(hr))
294 return hr;
295
296 hr = m_Client->QueryInterface(IID_PPV_ARG(IDeskBarClient, &dbc));
297 if (FAILED_UNEXPECTEDLY(hr))
298 return hr;
299
300 // Windows calls this, but it appears to be unimplemented?
301 hr = dbc->SetModeDBC(1);
302 // Allow it to fail with E_NOTIMPL.
303
304 // No clue about the arg, using anything != 0
305 hr = dbc->UIActivateDBC(TRUE);
306 if (FAILED_UNEXPECTEDLY(hr))
307 return hr;
308
309 RECT rc = { 0 };
310 hr = dbc->GetSize(0, &rc);
311 if (FAILED_UNEXPECTEDLY(hr))
312 return hr;
313
314 // Unknown meaning
315 const int CMD = 19;
316 const int CMD_EXEC_OPT = 0;
317
318 hr = IUnknown_QueryServiceExec(m_Client, SID_SMenuBandChild, &CLSID_MenuBand, CMD, CMD_EXEC_OPT, NULL, NULL);
319 if (FAILED_UNEXPECTEDLY(hr))
320 return hr;
321
322 ::AdjustWindowRect(&rc, ::GetWindowLong(m_hWnd, GWL_STYLE), FALSE);
323 ::OffsetRect(&rc, -rc.left, -rc.top);
324
325 if (m_Banner != NULL)
326 {
327 BITMAP bm;
328 ::GetObject(m_Banner, sizeof(bm), &bm);
329 rc.right += bm.bmWidth;
330 }
331
332 RECT rcWorkArea;
333 GetWindowRect(GetDesktopWindow(), &rcWorkArea);
334 int waHeight = rcWorkArea.bottom - rcWorkArea.top;
335
336 int x = ppt->x;
337 int y = ppt->y;
338 int cx = rc.right - rc.left;
339 int cy = rc.bottom - rc.top;
340
341 switch (dwFlags & 0xFF000000)
342 {
343 case MPPF_BOTTOM:
344 x = ppt->x;
345 y = ppt->y - rc.bottom;
346 break;
347 case MPPF_RIGHT:
348 x = ppt->x + rc.left;
349 y = ppt->y + rc.top;
350 break;
351 case MPPF_TOP | MPPF_ALIGN_LEFT:
352 x = ppt->x - rc.right;
353 y = ppt->y + rc.top;
354 break;
355 case MPPF_TOP | MPPF_ALIGN_RIGHT:
356 x = ppt->x;
357 y = ppt->y + rc.top;
358 break;
359 }
360
361 if (x + cx > rcWorkArea.right)
362 {
363 // FIXME: Works, but it's oversimplified.
364 x = prcExclude->left - cx;
365 dwFlags = (dwFlags & (~MPPF_TOP)) | MPPF_LEFT;
366 }
367
368 if (y < rcWorkArea.top)
369 {
370 y = rcWorkArea.top;
371 }
372
373 if (cy > waHeight)
374 {
375 cy = waHeight;
376 }
377
378 if (y + cy > rcWorkArea.bottom)
379 {
380 y = rcWorkArea.bottom - cy;
381 }
382
383 this->SetWindowPos(HWND_TOPMOST, x, y, cx, cy, SWP_SHOWWINDOW);
384
385 m_ShowFlags = dwFlags;
386 m_Shown = true;
387
388 // HACK: The bar needs to be notified of the size AFTER it is shown.
389 // Quick & dirty way of getting it done.
390 BOOL bHandled;
391 _OnSize(WM_SIZE, 0, 0, bHandled);
392
393 UIActivateIO(TRUE, NULL);
394
395 if (dwFlags & (MPPF_INITIALSELECT | MPPF_FINALSELECT))
396 {
397 const int CMD_SELECT = 5;
398 int CMD_SELECT_OPTS = dwFlags & MPPF_INITIALSELECT ? 0 : -2;
399 IUnknown_QueryServiceExec(m_Client, SID_SMenuBandChild, &CLSID_MenuBand, CMD_SELECT, CMD_SELECT_OPTS, NULL, NULL);
400 }
401
402 return S_OK;
403 }
404
405 HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetIconSize(THIS_ DWORD iIcon)
406 {
407 HRESULT hr;
408 m_IconSize = iIcon;
409
410 // Unknown meaning (set flags? set icon size?)
411 const int CMD = 16;
412 const int CMD_EXEC_OPT = iIcon ? 0 : 2; // seems to work
413
414 hr = IUnknown_QueryServiceExec(m_Client, SID_SMenuBandChild, &CLSID_MenuBand, CMD, CMD_EXEC_OPT, NULL, NULL);
415 if (FAILED_UNEXPECTEDLY(hr))
416 return hr;
417
418 BOOL bHandled;
419 _OnSize(WM_SIZE, 0, 0, bHandled);
420
421 return hr;
422 }
423
424 HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetIconSize(THIS_ DWORD* piIcon)
425 {
426 if (piIcon)
427 *piIcon = m_IconSize;
428 return S_OK;
429 }
430
431 HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetBitmap(THIS_ HBITMAP hBitmap)
432 {
433 m_Banner = hBitmap;
434
435 BOOL bHandled;
436 _OnSize(WM_SIZE, 0, 0, bHandled);
437
438 return S_OK;
439 }
440
441 HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetBitmap(THIS_ HBITMAP* phBitmap)
442 {
443 if (phBitmap)
444 *phBitmap = m_Banner;
445 return S_OK;
446 }
447
448 HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetSubMenu(IMenuPopup *pmp, BOOL fSet)
449 {
450 // Called by the MenuBand to assign itself as the logical child of the DeskBar
451
452 if (fSet)
453 {
454 m_SubMenuChild = pmp;
455 }
456 else
457 {
458 if (m_SubMenuChild)
459 {
460 if (pmp == m_SubMenuChild)
461 {
462 m_SubMenuChild = NULL;
463 }
464 }
465 }
466 return S_OK;
467 }
468
469 HRESULT STDMETHODCALLTYPE CMenuDeskBar::OnSelect(DWORD dwSelectType)
470 {
471 CComPtr<IDeskBar> safeThis = this;
472
473 /* As far as I can tell, the submenu hierarchy looks like this:
474 *
475 * The DeskBar's Child is the Band it contains.
476 * The DeskBar's Parent is the SID_SMenuPopup of the Site.
477 *
478 * The Band's Child is the IMenuPopup of the child submenu.
479 * The Band's Parent is the SID_SMenuPopup of the Site (the DeskBar).
480 *
481 * When the DeskBar receives a selection event:
482 * If it requires closing the window, it will notify the Child (Band) using CancelLevel.
483 * If it has to spread upwards (everything but CancelLevel), it will notify the Parent.
484 *
485 * When the Band receives a selection event, this is where it gets fuzzy:
486 * In which cases does it call the Parent? Probably not CancelLevel.
487 * In which cases does it call the Child?
488 * How does it react to calls?
489 *
490 */
491
492 CComPtr<IMenuPopup> oldParent = m_SubMenuParent;
493
494 switch (dwSelectType)
495 {
496 case MPOS_EXECUTE:
497 case MPOS_FULLCANCEL:
498 case MPOS_CANCELLEVEL:
499
500 _CloseBar();
501
502 if (dwSelectType == MPOS_CANCELLEVEL)
503 return S_OK;
504
505 case MPOS_SELECTLEFT:
506 case MPOS_SELECTRIGHT:
507 case MPOS_CHILDTRACKING:
508 if (oldParent)
509 return oldParent->OnSelect(dwSelectType);
510 break;
511 }
512
513 return S_OK;
514 }
515
516 HRESULT CMenuDeskBar::_CloseBar()
517 {
518 CComPtr<IDeskBar> safeThis = this;
519 CComPtr<IDeskBarClient> dbc;
520 HRESULT hr;
521
522 m_Shown = false;
523
524 if (m_SubMenuParent)
525 {
526 m_SubMenuParent->SetSubMenu(this, FALSE);
527 }
528
529 if (m_SubMenuChild)
530 {
531 hr = m_SubMenuChild->OnSelect(MPOS_CANCELLEVEL);
532 if (FAILED_UNEXPECTEDLY(hr))
533 return hr;
534 }
535
536 hr = m_Client->QueryInterface(IID_PPV_ARG(IDeskBarClient, &dbc));
537 if (FAILED_UNEXPECTEDLY(hr))
538 return hr;
539
540 hr = dbc->UIActivateDBC(FALSE);
541 if (FAILED_UNEXPECTEDLY(hr))
542 return hr;
543
544 SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE);
545
546 return UIActivateIO(FALSE, NULL);
547 }
548
549 BOOL CMenuDeskBar::_IsSubMenuParent(HWND hwnd)
550 {
551 CComPtr<IMenuPopup> popup = m_SubMenuParent;
552
553 while (popup)
554 {
555 HRESULT hr;
556 CComPtr<IOleWindow> window;
557
558 hr = popup->QueryInterface(IID_PPV_ARG(IOleWindow, &window));
559 if (FAILED_UNEXPECTEDLY(hr))
560 return FALSE;
561
562 HWND parent;
563
564 hr = window->GetWindow(&parent);
565 if (SUCCEEDED(hr) && hwnd == parent)
566 return TRUE;
567
568 popup = NULL;
569 hr = IUnknown_GetSite(window, IID_PPV_ARG(IMenuPopup, &popup));
570 if (FAILED(hr))
571 return FALSE;
572 }
573
574 return FALSE;
575 }
576
577 LRESULT CMenuDeskBar::_OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
578 {
579 if (m_Client)
580 {
581 RECT rc;
582
583 GetClientRect(&rc);
584
585 if (m_Banner != NULL)
586 {
587 BITMAP bm;
588 ::GetObject(m_Banner, sizeof(bm), &bm);
589 rc.left += bm.bmWidth;
590 }
591
592 ::SetWindowPos(m_ClientWindow, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 0);
593 }
594
595 return 0;
596 }
597
598 LRESULT CMenuDeskBar::_OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
599 {
600 if (!m_Client)
601 return 0;
602
603 CComPtr<IWinEventHandler> winEventHandler;
604 HRESULT hr = m_Client->QueryInterface(IID_PPV_ARG(IWinEventHandler, &winEventHandler));
605 if (FAILED_UNEXPECTEDLY(hr))
606 return 0;
607
608 if (winEventHandler)
609 {
610 LRESULT result;
611 hr = winEventHandler->OnWinEvent(NULL, uMsg, wParam, lParam, &result);
612 if (FAILED_UNEXPECTEDLY(hr))
613 return 0;
614 return result;
615 }
616
617 return 0;
618 }
619
620 LRESULT CMenuDeskBar::_OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
621 {
622 bHandled = FALSE;
623
624 if (m_Banner && !m_IconSize)
625 {
626 BITMAP bm;
627 PAINTSTRUCT ps;
628 HDC hdc = BeginPaint(&ps);
629
630 HDC hdcMem = ::CreateCompatibleDC(hdc);
631 HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_Banner);
632
633 ::GetObject(m_Banner, sizeof(bm), &bm);
634
635 RECT rc;
636 if (!GetClientRect(&rc))
637 WARN("GetClientRect failed\n");
638
639 const int bx = bm.bmWidth;
640 const int by = bm.bmHeight;
641 const int cy = rc.bottom;
642
643 TRACE("Painting banner: %d by %d\n", bm.bmWidth, bm.bmHeight);
644
645 if (!::StretchBlt(hdc, 0, 0, bx, cy - by, hdcMem, 0, 0, bx, 1, SRCCOPY))
646 WARN("StretchBlt failed\n");
647
648 if (!::BitBlt(hdc, 0, cy - by, bx, by, hdcMem, 0, 0, SRCCOPY))
649 WARN("BitBlt failed\n");
650
651 ::SelectObject(hdcMem, hbmOld);
652 ::DeleteDC(hdcMem);
653
654 EndPaint(&ps);
655 }
656
657 return TRUE;
658 }
659
660 LRESULT CMenuDeskBar::_OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
661 {
662 // BUG in ReactOS: WM_ACTIVATE/WA_INACTIVE makes no sense with lParam==hWnd
663 if (LOWORD(wParam) != 0 || reinterpret_cast<HWND>(lParam) == m_hWnd)
664 {
665 return 0;
666 }
667
668 // HACK! I just want it to work !!!
669 CComPtr<IDeskBar> db;
670 HRESULT hr = IUnknown_QueryService(m_Client, SID_SMenuBandChild, IID_PPV_ARG(IDeskBar, &db));
671 if (FAILED_UNEXPECTEDLY(hr))
672 return 0;
673
674 CComPtr<IUnknown> punk;
675
676 hr = db->GetClient(&punk);
677 if (FAILED_UNEXPECTEDLY(hr))
678 return 0;
679
680 if (!punk && m_Shown)
681 {
682 if (!_IsSubMenuParent(reinterpret_cast<HWND>(lParam)))
683 {
684 OnSelect(MPOS_FULLCANCEL);
685 }
686 }
687
688 return 0;
689 }
690
691 LRESULT CMenuDeskBar::_OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
692 {
693 return MA_NOACTIVATE;
694 }
695
696 LRESULT CMenuDeskBar::_OnAppActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
697 {
698 if (wParam == 0 && m_Shown)
699 {
700 OnSelect(MPOS_FULLCANCEL);
701 }
702 return 0;
703 }