1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_fpicker.hxx"
30 
31 //------------------------------------------------------------------------
32 // includes
33 //------------------------------------------------------------------------
34 
35 #include <tchar.h>
36 #include <osl/diagnose.h>
37 #include "../misc/WinImplHelper.hxx"
38 #include "FileOpenDlg.hxx"
39 
40 //------------------------------------------------------------------------
41 // constants
42 //------------------------------------------------------------------------
43 
44 namespace /* private */
45 {
46     // we choose such large buffers because the size of
47     // an single line edit field can be up to 32k; if
48     // a user has a multi selection FilePicker and selects
49     // a lot of files in a large directory we may reach this
50     // limit and don't want to get out of memory;
51     // another much more elegant way would be to subclass the
52     // FileOpen dialog and overload the BM_CLICK event of the
53     // OK button so that we determine the size of the text
54     // currently in the edit field and resize our buffer
55     // appropriately - in the future we will do this
56     const size_t MAX_FILENAME_BUFF_SIZE  = 32000;
57     const size_t MAX_FILETITLE_BUFF_SIZE = 32000;
58     const size_t MAX_FILTER_BUFF_SIZE    = 4096;
59 
60     const LPTSTR CURRENT_INSTANCE = TEXT("CurrInst");
61 
62     //------------------------------------------
63     // find an appropriate parent window
64     //------------------------------------------
65 
66     inline bool is_current_process_window(HWND hwnd)
67     {
68         DWORD pid;
69         GetWindowThreadProcessId(hwnd, &pid);
70         return (pid == GetCurrentProcessId());
71     }
72 
73     HWND choose_parent_window()
74     {
75         HWND hwnd_parent = GetForegroundWindow();
76         if (!is_current_process_window(hwnd_parent))
77             hwnd_parent = GetDesktopWindow();
78 
79         return hwnd_parent;
80     }
81 };
82 
83 //------------------------------------------------------------------------
84 //
85 //------------------------------------------------------------------------
86 
87 CFileOpenDialog::CFileOpenDialog(
88 	bool bFileOpenDialog,
89 	sal_uInt32 dwFlags,
90 	sal_uInt32 dwTemplateId,
91 	HINSTANCE hInstance) :
92 	m_hwndFileOpenDlg(0),
93 	m_hwndFileOpenDlgChild(0),
94 	m_bFileOpenDialog(bFileOpenDialog),
95 	m_filterBuffer(MAX_FILTER_BUFF_SIZE),
96 	m_fileTitleBuffer(MAX_FILETITLE_BUFF_SIZE),
97 	m_helperBuffer(MAX_FILENAME_BUFF_SIZE),
98 	m_fileNameBuffer(MAX_FILENAME_BUFF_SIZE),
99 	m_pfnBaseDlgProc(0)
100 {
101 	// initialize the OPENFILENAME struct
102 	if (IsWindows2000Platform() || IsWindowsME())
103 	{
104 		ZeroMemory(&m_ofn, sizeof(m_ofn));
105 		m_ofn.lStructSize = sizeof(m_ofn);
106 	}
107 	else // OSVER < Win2000
108 	{
109         // the size of the OPENFILENAME structure is different
110         // under windows < win2000
111 		ZeroMemory(&m_ofn, _OPENFILENAME_SIZE_VERSION_400);
112 		m_ofn.lStructSize = _OPENFILENAME_SIZE_VERSION_400;
113 	}
114 
115     // 0x02000000 for #97681, sfx will make the entry into
116     // the recent document list
117 	m_ofn.Flags |= dwFlags |
118 				   OFN_EXPLORER |
119 		           OFN_ENABLEHOOK |
120 		           OFN_HIDEREADONLY |
121 				   OFN_PATHMUSTEXIST |
122 				   OFN_FILEMUSTEXIST |
123                    OFN_OVERWRITEPROMPT |
124 				   OFN_ENABLESIZING |
125                    OFN_DONTADDTORECENT; // 0x02000000 -> OFN_DONTADDTORECENT only available with new platform sdk
126 
127     // it is a little hack but how else could
128     // we get a parent window (using a vcl window?)
129     m_ofn.hwndOwner = choose_parent_window();
130 
131 	m_ofn.lpstrFile = reinterpret_cast<LPTSTR>(const_cast<sal_Unicode*>(m_fileNameBuffer.getStr()));
132 	m_ofn.nMaxFile  = m_fileNameBuffer.getCapacity();
133 
134 	m_ofn.lpstrFileTitle = reinterpret_cast<LPTSTR>(const_cast<sal_Unicode*>(m_fileTitleBuffer.getStr()));
135 	m_ofn.nMaxFileTitle  = m_fileTitleBuffer.getCapacity();
136 
137 	m_ofn.lpfnHook = CFileOpenDialog::ofnHookProc;
138 
139 	// set a custom template
140 
141 	if (dwTemplateId)
142 	{
143 		OSL_ASSERT(hInstance);
144 
145 		m_ofn.Flags          |= OFN_ENABLETEMPLATE;
146 		m_ofn.lpTemplateName  = MAKEINTRESOURCE(dwTemplateId);
147 		m_ofn.hInstance       = hInstance;
148 	}
149 
150 	// set a pointer to myself as ofn parameter
151 	m_ofn.lCustData = reinterpret_cast<long>(this);
152 }
153 
154 //------------------------------------------------------------------------
155 //
156 //------------------------------------------------------------------------
157 
158 CFileOpenDialog::~CFileOpenDialog()
159 {
160 }
161 
162 //------------------------------------------------------------------------
163 //
164 //------------------------------------------------------------------------
165 
166 void SAL_CALL CFileOpenDialog::setTitle(const rtl::OUString& aTitle)
167 {
168 	m_dialogTitle = aTitle;
169 	m_ofn.lpstrTitle = reinterpret_cast<LPCTSTR>(m_dialogTitle.getStr());
170 }
171 
172 //------------------------------------------------------------------------
173 //
174 //------------------------------------------------------------------------
175 
176 void CFileOpenDialog::setFilter(const rtl::OUString& aFilter)
177 {
178     // Format is like
179     // "*.TXT" or multiple separate by ';' like "*.TXT;*.DOC;*.SXW"
180     // Do not include spaces in the pattern string
181 	m_filterBuffer.ensureCapacity(aFilter.getLength());
182 	m_filterBuffer.setLength(0);
183 	m_filterBuffer.append(aFilter);
184 	m_ofn.lpstrFilter = reinterpret_cast<LPCTSTR>(m_filterBuffer.getStr());
185 }
186 
187 //------------------------------------------------------------------------
188 //
189 //------------------------------------------------------------------------
190 
191 bool CFileOpenDialog::setFilterIndex(sal_uInt32 aIndex)
192 {
193 	OSL_ASSERT(aIndex > 0);
194 	m_ofn.nFilterIndex = aIndex;
195 	return sal_True;
196 }
197 
198 //------------------------------------------------------------------------
199 //
200 //------------------------------------------------------------------------
201 
202 sal_uInt32 CFileOpenDialog::getSelectedFilterIndex() const
203 {
204 	return m_ofn.nFilterIndex;
205 }
206 
207 //------------------------------------------------------------------------
208 //
209 //------------------------------------------------------------------------
210 
211 void SAL_CALL CFileOpenDialog::setDefaultName(const rtl::OUString& aName)
212 {
213 	m_fileNameBuffer.setLength(0);
214 	m_fileNameBuffer.append(aName);
215 	m_ofn.lpstrFile = reinterpret_cast<LPTSTR>(const_cast<sal_Unicode*>(m_fileNameBuffer.getStr()));
216 }
217 
218 //------------------------------------------------------------------------
219 //
220 //------------------------------------------------------------------------
221 
222 void SAL_CALL CFileOpenDialog::setDisplayDirectory(const rtl::OUString& aDirectory)
223 {
224 	m_displayDirectory = aDirectory;
225 	m_ofn.lpstrInitialDir = reinterpret_cast<LPCTSTR>(m_displayDirectory.getStr());
226 }
227 
228 //------------------------------------------------------------------------
229 //
230 //------------------------------------------------------------------------
231 
232 rtl::OUString SAL_CALL CFileOpenDialog::getLastDisplayDirectory() const
233 {
234 	return m_displayDirectory;
235 }
236 
237 //------------------------------------------------------------------------
238 //
239 //------------------------------------------------------------------------
240 
241 rtl::OUString SAL_CALL CFileOpenDialog::getFullFileName() const
242 {
243 	return rtl::OUString(m_fileNameBuffer.getStr(),
244 		_wcslenex(m_fileNameBuffer.getStr()));
245 }
246 
247 //------------------------------------------------------------------------
248 //
249 //------------------------------------------------------------------------
250 
251 rtl::OUString SAL_CALL CFileOpenDialog::getFileName() const
252 {
253 	return rtl::OUString(m_fileTitleBuffer);
254 }
255 
256 //------------------------------------------------------------------------
257 //
258 //------------------------------------------------------------------------
259 
260 rtl::OUString CFileOpenDialog::getFileExtension()
261 {
262 	if (m_ofn.nFileExtension)
263 		return rtl::OUString(m_fileNameBuffer.getStr() + m_ofn.nFileExtension,
264 			rtl_ustr_getLength(m_fileNameBuffer.getStr() + m_ofn.nFileExtension));
265 
266 	return rtl::OUString();
267 }
268 
269 //------------------------------------------------------------------------
270 //
271 //------------------------------------------------------------------------
272 
273 void CFileOpenDialog::setDefaultFileExtension(const rtl::OUString& aExtension)
274 {
275 	m_defaultExtension = aExtension;
276 	m_ofn.lpstrDefExt  = reinterpret_cast<LPCTSTR>(m_defaultExtension.getStr());
277 }
278 
279 //------------------------------------------------------------------------
280 //
281 //------------------------------------------------------------------------
282 
283 void SAL_CALL CFileOpenDialog::setMultiSelectionMode(bool bMode)
284 {
285 	if (bMode)
286 		m_ofn.Flags |= OFN_ALLOWMULTISELECT;
287 	else
288 		m_ofn.Flags &= ~OFN_ALLOWMULTISELECT;
289 }
290 
291 //------------------------------------------------------------------------
292 //
293 //------------------------------------------------------------------------
294 
295 bool SAL_CALL CFileOpenDialog::getMultiSelectionMode() const
296 {
297 	return ((m_ofn.Flags & OFN_ALLOWMULTISELECT) > 0);
298 }
299 
300 //------------------------------------------------------------------------
301 //
302 //------------------------------------------------------------------------
303 
304 sal_Int16 SAL_CALL CFileOpenDialog::doModal()
305 {
306 	sal_Int16 nRC = -1;
307 
308 	// pre-processing
309 	if (preModal())
310 	{
311 		bool bRet;
312 
313         if (m_bFileOpenDialog)
314 	        bRet = m_GetFileNameWrapper.getOpenFileName(
315 				reinterpret_cast<LPOPENFILENAME>(&m_ofn));
316         else
317             bRet = m_GetFileNameWrapper.getSaveFileName(
318 				reinterpret_cast<LPOPENFILENAME>(&m_ofn));
319 
320 	    nRC = 1;
321 
322 		if (!bRet)
323 			nRC = (0 == m_GetFileNameWrapper.commDlgExtendedError()) ? 0 : -1;
324 
325 		// post-processing
326 		postModal(nRC);
327 	}
328 
329 	return nRC;
330 }
331 
332 //------------------------------------------------------------------------
333 //
334 //------------------------------------------------------------------------
335 
336 sal_uInt32 SAL_CALL CFileOpenDialog::getLastDialogError() const
337 {
338 	return CommDlgExtendedError();
339 }
340 
341 //------------------------------------------------------------------------
342 //
343 //------------------------------------------------------------------------
344 
345 bool SAL_CALL CFileOpenDialog::preModal()
346 {
347 	return sal_True;
348 }
349 
350 //------------------------------------------------------------------------
351 //
352 //------------------------------------------------------------------------
353 
354 void SAL_CALL CFileOpenDialog::postModal(sal_Int16 nDialogResult)
355 {
356 	OSL_ASSERT((-1 <= nDialogResult) && (nDialogResult <= 1));
357 
358 	if (1 == nDialogResult)
359 	{
360 		// Attention: assuming that nFileOffset is always greater 0 because under
361 		// Windows there is always a drive letter or a server in a complete path
362 		// the OPENFILENAME docu never says that nFileOffset can be 0
363 		m_displayDirectory = rtl::OUString(reinterpret_cast<const sal_Unicode*>(m_ofn.lpstrFile),m_ofn.nFileOffset);
364 	}
365 }
366 
367 //------------------------------------------------------------------------
368 //
369 //------------------------------------------------------------------------
370 
371 rtl::OUString SAL_CALL CFileOpenDialog::getCurrentFilePath() const
372 {
373 	OSL_ASSERT(IsWindow(m_hwndFileOpenDlg));
374 
375 	LPARAM nLen = SendMessage(
376 		m_hwndFileOpenDlg,
377 		CDM_GETFILEPATH,
378 		m_helperBuffer.getCapacity(),
379 		reinterpret_cast<LPARAM>(m_helperBuffer.getStr()));
380 
381 	if (nLen > 0)
382 	{
383 		m_helperBuffer.setLength((nLen * sizeof(sal_Unicode)) - 1);
384 		return rtl::OUString(m_helperBuffer);
385 	}
386 	return rtl::OUString();
387 }
388 
389 //------------------------------------------------------------------------
390 //
391 //------------------------------------------------------------------------
392 
393 rtl::OUString SAL_CALL CFileOpenDialog::getCurrentFolderPath() const
394 {
395 	OSL_ASSERT(IsWindow(m_hwndFileOpenDlg));
396 
397 	LPARAM nLen = SendMessage(
398 		m_hwndFileOpenDlg,
399 		CDM_GETFOLDERPATH,
400 		m_helperBuffer.getCapacity(),
401 		reinterpret_cast<LPARAM>(m_helperBuffer.getStr()));
402 
403 	if (nLen > 0)
404 	{
405 		m_helperBuffer.setLength((nLen * sizeof(sal_Unicode)) - 1);
406 		return rtl::OUString(m_helperBuffer);
407 	}
408 	return rtl::OUString();
409 }
410 
411 //------------------------------------------------------------------------
412 //
413 //------------------------------------------------------------------------
414 
415 rtl::OUString SAL_CALL CFileOpenDialog::getCurrentFileName() const
416 {
417 	OSL_ASSERT(IsWindow(m_hwndFileOpenDlg));
418 
419 	LPARAM nLen = SendMessage(
420 		m_hwndFileOpenDlg,
421 		CDM_GETSPEC,
422 		m_helperBuffer.getCapacity(),
423 		reinterpret_cast<LPARAM>(m_helperBuffer.getStr()));
424 
425 	if (nLen > 0)
426 	{
427 		m_helperBuffer.setLength((nLen * sizeof(sal_Unicode)) - 1);
428 		return rtl::OUString(m_helperBuffer);
429 	}
430 	return rtl::OUString();
431 }
432 
433 //------------------------------------------------------------------------
434 //
435 //------------------------------------------------------------------------
436 
437 sal_uInt32 SAL_CALL CFileOpenDialog::onShareViolation(const rtl::OUString&)
438 {
439 	return 0;
440 }
441 
442 //------------------------------------------------------------------------
443 //
444 //------------------------------------------------------------------------
445 
446 sal_uInt32 SAL_CALL CFileOpenDialog::onFileOk()
447 {
448 	return 0;
449 }
450 
451 //------------------------------------------------------------------------
452 //
453 //------------------------------------------------------------------------
454 
455 void SAL_CALL CFileOpenDialog::onSelChanged(HWND)
456 {
457 }
458 
459 //------------------------------------------------------------------------
460 //
461 //------------------------------------------------------------------------
462 
463 void SAL_CALL CFileOpenDialog::onHelp()
464 {
465 }
466 
467 //------------------------------------------------------------------------
468 //
469 //------------------------------------------------------------------------
470 
471 void SAL_CALL CFileOpenDialog::onInitDone()
472 {
473     centerPositionToParent();
474 }
475 
476 //------------------------------------------------------------------------
477 //
478 //------------------------------------------------------------------------
479 
480 void SAL_CALL CFileOpenDialog::onFolderChanged()
481 {
482 }
483 
484 //------------------------------------------------------------------------
485 //
486 //------------------------------------------------------------------------
487 
488 void SAL_CALL CFileOpenDialog::onTypeChanged(sal_uInt32)
489 {
490 }
491 
492 //------------------------------------------------------------------------
493 //
494 //------------------------------------------------------------------------
495 
496 sal_uInt32 SAL_CALL CFileOpenDialog::onCtrlCommand(HWND, sal_uInt16, sal_uInt16)
497 {
498 	return 0;
499 }
500 
501 //------------------------------------------------------------------------
502 //
503 //------------------------------------------------------------------------
504 
505 sal_uInt32 SAL_CALL CFileOpenDialog::onWMNotify( HWND, LPOFNOTIFY lpOfNotify )
506 {
507 	switch(lpOfNotify->hdr.code)
508 	{
509 	case CDN_SHAREVIOLATION:
510 		return onShareViolation(reinterpret_cast<const sal_Unicode*>(lpOfNotify->pszFile));
511 
512 	case CDN_FILEOK:
513 		return onFileOk();
514 
515 	case CDN_SELCHANGE:
516 		onSelChanged(lpOfNotify->hdr.hwndFrom);
517 		break;
518 
519 	case CDN_HELP:
520 		onHelp();
521 		break;
522 
523 	case CDN_INITDONE:
524 		onInitDone();
525 		break;
526 
527 	case CDN_FOLDERCHANGE:
528 		onFolderChanged();
529 		break;
530 
531 	case CDN_TYPECHANGE:
532         m_ofn.nFilterIndex = lpOfNotify->lpOFN->nFilterIndex;
533 		onTypeChanged(lpOfNotify->lpOFN->nFilterIndex);
534 		break;
535 	}
536 
537 	return 0;
538 }
539 
540 //------------------------------------------------------------------------
541 //
542 //------------------------------------------------------------------------
543 
544 void SAL_CALL CFileOpenDialog::handleInitDialog(HWND hwndDlg, HWND hwndChild)
545 {
546 	m_hwndFileOpenDlg      = hwndDlg;
547 	m_hwndFileOpenDlgChild = hwndChild;
548 
549 	OSL_ASSERT(GetParent(hwndChild) == hwndDlg);
550 
551 	// calling virtual function which the
552 	// client can overload
553 	onInitDialog(hwndDlg);
554 }
555 
556 //------------------------------------------------------------------------
557 //
558 //------------------------------------------------------------------------
559 
560 unsigned int CALLBACK CFileOpenDialog::ofnHookProc(
561 	HWND hChildDlg, unsigned int uiMsg, WPARAM wParam, LPARAM lParam)
562 {
563     HWND hwndDlg = GetParent(hChildDlg);
564     CFileOpenDialog* pImpl = NULL;
565 
566 	switch( uiMsg )
567 	{
568 	case WM_INITDIALOG:
569         {
570             _LPOPENFILENAME lpofn = reinterpret_cast<_LPOPENFILENAME>(lParam);
571             pImpl = reinterpret_cast<CFileOpenDialog*>(lpofn->lCustData);
572             OSL_ASSERT(pImpl);
573 
574             // subclass the base dialog for WM_NCDESTROY processing
575             pImpl->m_pfnBaseDlgProc =
576 		        reinterpret_cast<WNDPROC>(
577 			        SetWindowLong(
578 			            hwndDlg,
579 			            GWL_WNDPROC,
580                         reinterpret_cast<LONG>(CFileOpenDialog::BaseDlgProc)));
581             // connect the instance handle to the window
582             SetProp(hwndDlg, CURRENT_INSTANCE, pImpl);
583 		    pImpl->handleInitDialog(hwndDlg, hChildDlg);
584         }
585 		return 0;
586 
587 	case WM_NOTIFY:
588         {
589             pImpl = getCurrentInstance(hwndDlg);
590 		    return pImpl->onWMNotify(
591 			    hChildDlg, reinterpret_cast<LPOFNOTIFY>(lParam));
592         }
593 
594 	case WM_COMMAND:
595         {
596             pImpl = getCurrentInstance(hwndDlg);
597             OSL_ASSERT(pImpl);
598 
599 		    return pImpl->onCtrlCommand(
600 			    hChildDlg, LOWORD(wParam), HIWORD(lParam));
601         }
602 	}
603 
604 	return 0;
605 }
606 
607 //------------------------------------------------------------------------
608 //
609 //------------------------------------------------------------------------
610 
611 LRESULT CALLBACK CFileOpenDialog::BaseDlgProc(
612     HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam)
613 {
614 	CFileOpenDialog* pImpl = 0;
615 
616 	if (WM_NCDESTROY == wMessage)
617 	{
618 		pImpl = reinterpret_cast<CFileOpenDialog*>(
619 			RemoveProp(hWnd,CURRENT_INSTANCE));
620 
621 		SetWindowLong(hWnd, GWL_WNDPROC,
622 			reinterpret_cast<LONG>(pImpl->m_pfnBaseDlgProc));
623 	}
624 	else
625 	{
626 		pImpl = getCurrentInstance(hWnd);
627 	}
628 
629 	OSL_ASSERT(pImpl);
630 
631 	return CallWindowProc(
632 		reinterpret_cast<WNDPROC>(pImpl->m_pfnBaseDlgProc),
633 		hWnd,wMessage,wParam,lParam);
634 }
635 
636 //------------------------------------------------------------------------
637 //
638 //------------------------------------------------------------------------
639 
640 CFileOpenDialog* SAL_CALL CFileOpenDialog::getCurrentInstance(HWND hwnd)
641 {
642     OSL_ASSERT(IsWindow( hwnd));
643     return reinterpret_cast<CFileOpenDialog*>(
644         GetProp(hwnd, CURRENT_INSTANCE));
645 }
646 
647 //------------------------------------------------------------------------
648 //
649 //------------------------------------------------------------------------
650 
651 void SAL_CALL CFileOpenDialog::centerPositionToParent() const
652 {
653     OSL_PRECOND(IsWindow(m_hwndFileOpenDlg), "no dialog window, call method only after or in onInitDone");
654 
655     HWND hwndParent = m_ofn.hwndOwner;
656 
657     if (!IsWindow(hwndParent))
658         hwndParent = GetDesktopWindow();
659 
660     OSL_ASSERT(IsWindow(hwndParent));
661 
662     RECT rcPar;
663     GetWindowRect(hwndParent, &rcPar);
664 
665     RECT rcDlg;
666     GetWindowRect(m_hwndFileOpenDlg, &rcDlg);
667 
668     int lDlgW = rcDlg.right  - rcDlg.left;
669     int lDlgH = rcDlg.bottom - rcDlg.top;
670 
671 	int x = (rcPar.left + rcPar.right  - lDlgW) / 2;
672 	int y = (rcPar.top  + rcPar.bottom - lDlgH) / 2;
673 
674 	HDC hdc = GetDC(m_hwndFileOpenDlg);
675 
676     int hResol = GetDeviceCaps(hdc, HORZRES);
677     int vResol = GetDeviceCaps(hdc, VERTRES);
678 
679 	ReleaseDC(m_hwndFileOpenDlg, hdc);
680 
681     if (x < 0)
682         x = 0;
683     else if ((x + lDlgW) > hResol)
684         x = hResol - lDlgW;
685 
686     if (y < 0)
687         y = 0;
688     else if ((y + lDlgH) > vResol)
689         y = vResol - lDlgH;
690 
691     SetWindowPos(
692         m_hwndFileOpenDlg,
693         NULL, x, y, 0, 0,
694         SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE );
695 }
696