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