in reply to Re^3: Win32::GUI: how to find BrowseForFolder()'s handle?
in thread Win32::GUI: how to find BrowseForFolder()'s handle?

The code piece was just a code snippet, to illustrate the problem. Obviously in the OP it was not intended as a complete program. (See new code example below).

To recall the two problems:

1. The "BrowseForFolder()" window does not show up at the foreground, while all other windows do. This is disturbing and annoying, and can lead to many problems.

Here is a complete (compileable and running) code example. (5.014 is not essential)

use strict; use warnings; use 5.014; use Win32::GUI(); use Win32::GUI qw{ WS_EX_TOPMOST}; my ($InputDir, $TopDir, $InputFileName, $dw, $dh, $desktop, $Window); $TopDir = 'D:\My documents'; # Change this to an existing direcotry + of yours $desktop = Win32::GUI::GetDesktopWindow(); $dw = Win32::GUI::Width($desktop); $dh = Win32::GUI::Height($desktop); $Window = Win32::GUI::Window->new( -name => 'main', -text => 'Main win +dow', -pos => [20/100*$dw, 20/100*$dh], -size => [50/100*$dw, 60/100 +*$dh], -onTerminate => \&TerminateWindow, -addexstyle => WS_EX_TOPMOST, -dialogui => 1, -tabstop => 1 +, -cancel => 1, ); $Window -> AddButton ( -name => 'ButtonCommit', -pos => [10,10], -size =>[16/100*$dw,3.5/100*$dh], -text => 'Commit changes', -onCl +ick => \&Commit); sub Commit { $InputDir = Win32::GUI::BrowseForFolder( -root => $TopDir, -includefil +es => 1, -title => 'Select directory for parameter file', -text =>'Selext directory for parameter file', -size => [50/100*$dw, 50/100*$dh], -addexstyle => +WS_EX_TOPMOST,); $InputFileName = Win32::GUI::GetOpenFileName( -title => 'Select the i +nput file', -directory => $InputDir, -file => "\0" . " " x 256, -filter => ["Text files (*.txt)" => "*.txt", "All files", "*.* +", ], -text => 'text Select input file'); } # end sub Commit $Window ->Show(); Win32::GUI::Dialog(); sub TerminateWindow { return -1; }

Click the "Commit changes" button, then minimize the main window. Note that the "BrowseForFolder()" window hides behind other windows, and you need to minimize other windows to get to it. All other Perl Win32::GUI windows do open up at the foreground. Furthermore, note that -addexstyle => WS_EX_TOPMOST doesn't have an effect, while it usually does in Perl Win32::GUI windows.

Note: change the 'D:\My documents' to an existing directory of yours.

2. How does one find the desktop windows handles? If we could find BrowseForFolder()'s handle, we could raise it to the foreground (how?)

Many TIA

Helen

Replies are listed 'Best First'.
Re^5: Win32::GUI: how to find BrowseForFolder()'s handle?
by Anonymous Monk on Sep 22, 2012 at 08:00 UTC

    First some notes SSCCE (its like noise )

    The code piece was just a code snippet, to illustrate the problem.

    But you see, it did not illustrate the problem.

    Even if I went and made it compile, it still did not show the problem.

    You have to show how it doesn't work , just saying it doesn't work for getting solutions :)

    Obviously in the OP it was not intended as a complete program. (See new code example below).

    Hmm, if it was obvious, why insist the code compiles fine?

    Here is a complete (compileable and running) code example.

    Thanks. I see what you're talking about now. You can fix this by removing

    -addexstyle => WS_EX_TOPMOST,
    from $window/Main Window

    :D

    That may or may not be what you want, but its a fix ;D

    2. How does one find the desktop windows handles? If we could find BrowseForFolder()'s handle, we could raise it to the foreground (how?)

    If you wonder how it works, UTSL http://cpansearch.perl.org/src/ROBERTMAY/Win32-GUI-1.06/GUI.xs

    ##################################################################### +###### # (@)METHOD:BrowseForFolder(%OPTIONS) # Displays the standard "Browse For Folder" dialog box. Returns th +e # selected item's name, or undef if no item was selected or an err +or # occurred. # # Allowed B<%OPTIONS> are: # -title => STRING # the title for the dialog # -computeronly => 0/1 (default 0) # only enable computers to be selected # -domainonly => 0/1 (default 0) # only enable computers in the current domain or workgroup # -driveonly => 0/1 (default 0) # only enable drives to be selected # -editbox => 0/1 (default 0) # if 1, the dialog will include an edit field in which # the user can type the name of an item # -folderonly => 0/1 (default 0) # only enable folders to be selected # -includefiles => 0/1 (default 0) # the list will include files as well folders # -owner => WINDOW # A Win32::GUI::Window or Win32::GUI::DialogBox object specif +iying the # owner window for the dialog box # -printeronly => 0/1 (default 0) # only enable printers to be selected # -directory => PATH # the default start directory for browsing # -root => PATH or CONSTANT # the root directory for browsing; this can be either a # path or one of the following constants (minimum operating s +ystems or # Internet Explorer versions that support the constant are sh +own in # square brackets. NT denotes Windows NT 4.0, Windows 2000, X +P, etc.): # # CSIDL_FLAG_CREATE (0x8000) # [2000/ME] Combining this with any of the constants bel +ow will create the folder if it does not already exist. # CSIDL_ADMINTOOLS (0x0030) # [2000/ME] Administrative Tools directory for current u +ser # CSIDL_ALTSTARTUP (0x001d) # [All] Non-localized Startup directory in the Start men +u for current user # CSIDL_APPDATA (0x001a) # [IE4] Application data directory for current user # CSIDL_BITBUCKET (0x000a) # [All] Recycle Bin # CSIDL_CDBURN_AREA (0x003b) # [XP] Windows XP directory for files that will be burne +d to CD # CSIDL_COMMON_ADMINTOOLS (0x002f) # [2000/ME] Administrative Tools directory for all users # CSIDL_COMMON_ALTSTARTUP (0x001e) # [All] Non-localized Startup directory in the Start men +u for all users # CSIDL_COMMON_APPDATA (0x0023) # [2000/ME] Application data directory for all users # CSIDL_COMMON_DESKTOPDIRECTORY (0x0019) # [NT] Desktop directory for all users # CSIDL_COMMON_DOCUMENTS (0x002e) # [IE4] My Documents directory for all users # CSIDL_COMMON_FAVORITES (0x001f) # [NT] Favorites directory for all users # CSIDL_COMMON_MUSIC (0x0035) # [XP] Music directory for all users # CSIDL_COMMON_PICTURES (0x0036) # [XP] Image directory for all users # CSIDL_COMMON_PROGRAMS (0x0017) # [NT] Start menu "Programs" directory for all users # CSIDL_COMMON_STARTMENU (0x0016) # [NT] Start menu root directory for all users # CSIDL_COMMON_STARTUP (0x0018) # [NT] Start menu Startup directory for all users # CSIDL_COMMON_TEMPLATES (0x002d) # [NT] Document templates directory for all users # CSIDL_COMMON_VIDEO (0x0037) # [XP] Video directory for all users # CSIDL_CONTROLS (0x0003) # [All] Control Panel applets # CSIDL_COOKIES (0x0021) # [All] Cookies directory # CSIDL_DESKTOP (0x0000) # [All] Namespace root (shown as "Desktop", but is paren +t to my computer, control panel, my documents, etc.) # CSIDL_DESKTOPDIRECTORY (0x0010) # [All] Desktop directory (for desktop icons, folders, e +tc.) for the current user # CSIDL_DRIVES (0x0011) # [All] My Computer (drives and mapped network drives) # CSIDL_FAVORITES (0x0006) # [All] Favorites directory for the current user # CSIDL_FONTS (0x0014) # [All] Fonts directory # CSIDL_HISTORY (0x0022) # [All] Internet Explorer history items for the current +user # CSIDL_INTERNET (0x0001) # [All] Internet root # CSIDL_INTERNET_CACHE (0x0020) # [IE4] Temporary Internet Files directory for the curre +nt user # CSIDL_LOCAL_APPDATA (0x001c) # [2000/ME] Local (non-roaming) application data directo +ry for the current user # CSIDL_MYMUSIC (0x000d) # [All] My Music directory for the current user # CSIDL_MYPICTURES (0x0027) # [2000/ME] Image directory for the current user # CSIDL_MYVIDEO (0x000e) # [XP] Video directory for the current user # CSIDL_NETHOOD (0x0013) # [All] My Network Places directory for the current user # CSIDL_NETWORK (0x0012) # [All] Root of network namespace (Network Neighbourhood +) # CSIDL_PERSONAL (0x0005) # [All] My Documents directory for the current user # CSIDL_PRINTERS (0x0004) # [All] List of installed printers # CSIDL_PRINTHOOD (0x001b) # [All] Network printers directory for the current user # CSIDL_PROFILE (0x0028) # [2000/ME] The current user's profile directory # CSIDL_PROFILES (0x003e) # [XP] The directory that holds user profiles (see CSDIL +_PROFILE) # CSIDL_PROGRAM_FILES (0x0026) # [2000/ME] Program Files directory # CSIDL_PROGRAM_FILES_COMMON (0x002b) # [2000] Directory for files that are used by several ap +plications. Usually Program Files\Common # CSIDL_PROGRAMS (0x0002) # [All] Start menu "Programs" directory for the current +user # CSIDL_RECENT (0x0008) # [All] Recent Documents directory for the current user # CSIDL_SENDTO (0x0009) # [All] "Send To" directory for the current user # CSIDL_STARTMENU (0x000b) # [All] Start Menu root for the current user # CSIDL_STARTUP (0x0007) # [All] Start Menu "Startup" folder for the current user # CSIDL_SYSTEM (0x0025) # [2000/ME] System directory. Usually \Windows\System32 # CSIDL_TEMPLATES (0x0015) # [All] Document templates directory for the current use +r # CSIDL_WINDOWS (0x0024) # [2000/ME] Windows root directory, can also be accessed + via the environment variables %windir% or %SYSTEMROOT%. # void BrowseForFolder(...) PPCODE: BROWSEINFO bi; LPITEMIDLIST retval; LPITEMIDLIST pidl; LPSHELLFOLDER pDesktopFolder; OLECHAR olePath[MAX_PATH]; ULONG chEaten; HRESULT hr; int i, next_i; char folder[MAX_PATH]; char *option; ZeroMemory(&bi, sizeof(BROWSEINFO)); bi.pszDisplayName = folder; next_i = -1; for(i = 0; i < items; i++) { if(next_i == -1) { option = SvPV_nolen(ST(i)); if(strcmp(option, "-owner") == 0) { next_i = i + 1; bi.hwndOwner = (HWND) handle_From(NOTXSCALL ST(next_i) +); } else if(strcmp(option, "-title") == 0) { next_i = i + 1; bi.lpszTitle = SvPV_nolen(ST(next_i)); } else BitmaskOption("-computeronly", bi.ulFlags, BIF_BROW +SEFORCOMPUTER) } else BitmaskOption("-domainonly", bi.ulFlags, BIF_DONTGO +BELOWDOMAIN) } else BitmaskOption("-driveonly", bi.ulFlags, BIF_RETURNF +SANCESTORS) } else BitmaskOption("-editbox", bi.ulFlags, BIF_EDITBOX) } else BitmaskOption("-folderonly", bi.ulFlags, BIF_RETURN +ONLYFSDIRS) } else BitmaskOption("-includefiles", bi.ulFlags, BIF_BROW +SEINCLUDEFILES) } else BitmaskOption("-printeronly", bi.ulFlags, BIF_BROWS +EFORPRINTER) } else if(strcmp(option, "-directory") == 0) { next_i = i + 1; bi.lParam = (LPARAM) SvPV_nolen(ST(next_i)); bi.lpfn = BrowseForFolderProc; } else if(strcmp(option, "-root") == 0) { next_i = i + 1; if(SvIOK(ST(next_i))) { bi.pidlRoot = INT2PTR(LPCITEMIDLIST,SvIV(ST(next_i +))); } else { SHGetDesktopFolder(&pDesktopFolder); MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, SvPV_nolen(ST(next_i)), -1, olePath, MAX_PATH ); hr = pDesktopFolder->ParseDisplayName( // hr = IShellFolder::ParseDisplayName( NULL, NULL, olePath, &chEaten, &pidl, NULL ); if(FAILED(hr)) { W32G_WARN("Win32::GUI::BrowseForFolder: can't +get ITEMIDLIST for -root!"); pDesktopFolder->Release(); XSRETURN_UNDEF; } else { bi.pidlRoot = pidl; pDesktopFolder->Release(); } } } } else { next_i = -1; } } retval = SHBrowseForFolder(&bi); if(retval != NULL) { if(SHGetPathFromIDList(retval, folder)) { EXTEND(SP, 1); XST_mPV( 0, folder); XSRETURN(1); } else { XSRETURN_UNDEF; } } else { XSRETURN_UNDEF; }

    Would you look at that # -owner => WINDOW

    Yup, specifying   -owner => $Window, does the trick (it works), no WS_EX_TOPMOST required

      Thank you. That was instructive, and it actually solves the issue.

      (SSCCE and UTSL are instructive too - learned something new).

      A follow-up question: the role of the "-owner" option is not clear to me. Why and when is it necessary, and why does it fix the problem?

      TIA Helen

        A follow-up question: the role of the "-owner" option is not clear to me. Why and when is it necessary, and why does it fix the problem?

        It is necessary whenever you're using the functional interface

        If you had used $Window->BrowseForFolder() it would have happened automagically

        It lets the windowing system/ window manager, decide correctly to allow children of parent to display on top of parent , in effect it propagates the WS_EX_TOPMOST flag to the children