Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
OpenDialog ALLOWMULTISELECT
#1
How I get this viewing longnames?
#2
This function allows to select multiple files.

Function OpenSaveDialog2

Code:
Copy      Help
;/
function# save ~&s [~filter] [$defext] [~&initdir] [$title] [nodereferencelinks] [ARRAY(str)&multi] ;;save: 0 open, 1 save;  filter example: "Text files[]*.txt[]All Files[]*.*[]"

;Shows "Open" or "Save As" dialog and stores full path into
;str variable s. Returns 1 on Open or Save; 0 on Cancel.


;save – dialog type: 0 – "Open", 1 – "Save As".
;s – str variable that receives full path.
;filter – file types displayed in dialog. Consists of
;,description/pattern string pairs. Each string must end
;,with new line characters or null character.
;defext – default extension.
;initdir – str variable that sets initial directory
;,and receives selected file directory.
;;;;If initdir is not used, initial directory will be current
;;;;directory, and current directory may be changed. If initdir
;;;;is used, current directory will not be changed.
;title – dialog box title.
;nodereferencelinks - get path of shortcut file, not its target.
;multi - if used, Open dialog allows to select multiple files.
;;;;multi is populated with full paths. s can be 0.


;EXAMPLES
;str s
;if OpenSaveDialog2(0 &s "Text files[]*.txt[]All Files[]*.*[]" "txt")
;,out s


;ARRAY(str) a
;if(OpenSaveDialog2(0 0 "" "" 0 "" 0 a))

,;for(int'i 0 a.len) out a[i]


;def OFN_READONLY     0x1
def OFN_OVERWRITEPROMPT  0x2
def OFN_HIDEREADONLY  0x4
def OFN_NOCHANGEDIR  0x8
;def OFN_SHOWHELP     0x10
;def OFN_ENABLEHOOK   0x20
;def OFN_ENABLETEMPLATE  0x40
;def OFN_ENABLETEMPLATEHANDLE  0x80
;def OFN_NOVALIDATE   0x100

def OFN_ALLOWMULTISELECT  0x200
;def OFN_EXTENSIONDIFFERENT  0x400
;def OFN_PATHMUSTEXIST  0x800
;def OFN_FILEMUSTEXIST  0x1000
;def OFN_CREATEPROMPT  0x2000
;def OFN_SHAREAWARE   0x4000

def OFN_NOREADONLYRETURN  0x8000
;def OFN_NOTESTFILECREATE  0x10000
;def OFN_NONETWORKBUTTON  0x20000
;def OFN_NOLONGNAMES  0x40000

def OFN_EXPLORER     0x80000
def OFN_NODEREFERENCELINKS  0x100000
;def OFN_LONGNAMES    0x200000
;def OFN_SHAREFALLTHROUGH  2
;def OFN_SHARENOWARN  1
;def OFN_SHAREWARN    0

def FNERR_BUFFERTOOSMALL  0x3003
type OPENFILENAME lStructSize hwndOwner hInstance $lpstrFilter $lpstrCustomFilter nMaxCustFilter nFilterIndex $lpstrFile nMaxFile $lpstrFileTitle nMaxFileTitle $lpstrInitialDir $lpstrTitle flags @nFileOffset @nFileExtension $lpstrDefExt lCustData lpfnHook $lpTemplateName
dll comdlg32
,#GetOpenFileName OPENFILENAME*pOpenfilename
,#GetSaveFileName OPENFILENAME*pOpenfilename
,#CommDlgExtendedError

int multisel
if(&multi) multi.redim; if(!save) multisel=1

if(!&s or multisel) &s=&_s
s.all(iif(multisel 10000 MAX_PATH) 1)

OPENFILENAME op.lStructSize = sizeof(OPENFILENAME)
op.lpstrFile = s
op.nMaxFile = s.nc
op.hwndOwner=win
op.lpstrDefExt=defext
op.lpstrTitle=title

op.flags=OFN_HIDEREADONLY
if(nodereferencelinks) op.flags | OFN_NODEREFERENCELINKS
if(save) op.flags | OFN_OVERWRITEPROMPT | OFN_NOREADONLYRETURN
else if(multisel) op.flags | OFN_ALLOWMULTISELECT|OFN_EXPLORER

if(&initdir)
,initdir.searchpath(initdir "" 1); op.lpstrInitialDir=initdir
,str curdir.fix(GetCurrentDirectory(MAX_PATH curdir.all(MAX_PATH)))

;If as separators used newline characters, replace them to null characters:
rep
,int i=find(filter "[]" i)
,if(i>=0) filter[i]=0; i+1; filter.remove(i 1); else break
op.lpstrFilter = filter

if(save) i=GetSaveFileName(&op)
else i=GetOpenFileName(&op)
if(!i) s=""; ret

if(multisel)
,if(s[op.nFileOffset-1]) multi[multi.redim(1)]=s.lpstr ;;single
,else
,,int j k
,,for j op.nFileOffset s.nc
,,,k=len(s+j); if(!k) break
,,,multi[multi.redim(-1)].fromn(s op.nFileOffset-1 "\" 1 s+j k)
,,,j+k
else s.fix()

if(&initdir)
,initdir.fix(GetCurrentDirectory(MAX_PATH initdir.all(MAX_PATH)))
,if(curdir.len) SetCurrentDirectory(curdir)

ret 1

Example:
Code:
Copy      Help
ARRAY(str) a
if(OpenSaveDialog2(0 0 "" "" 0 "" 0 a))
,for(int'i 0 a.len) out a[i]
#3
Thanks.
#4
Is this possible? To put the choice into an array? Maybe already written?
Select All?

Stuart
#5
Example
Code:
Copy      Help
ARRAY(str)- t_af

str controls = "3"
str lb3
if(!ShowDialog("Dialog35" &Dialog35 &controls)) ret

out t_af


Function Dialog35 (example)
Code:
Copy      Help
;\Dialog_Editor
function# hDlg message wParam lParam

;BEGIN DIALOG
;0 "" 0x90C80A44 0x100 0 0 223 135 "Dialog"
;1 Button 0x54030001 0x4 120 116 48 14 "OK"
;2 Button 0x54030000 0x4 170 116 48 14 "Cancel"
;3 ListBox 0x54230109 0x200 4 4 130 109 ""
;4 Button 0x54032000 0x0 4 118 48 14 "Desktop"
;END DIALOG
;DIALOG EDITOR: "" 0x2020100 "" ""


;messages
sel message
,case WM_INITDIALOG
,case WM_DESTROY
,case WM_COMMAND goto messages2
ret
;messages2
sel wParam
,case 4 ;;Desktop
,int hlb=id(3 hDlg)
,SendMessage hlb LB_RESETCONTENT 0 0
,Dir d
,foreach(d "$Desktop$\*" FE_Dir)
,,SendMessage hlb LB_ADDSTRING 0 d.FileName
,,
,case IDOK
,ARRAY(str)- t_af
,LB_GetSelectedItems id(3 hDlg) t_af
,case IDCANCEL
ret 1

Function LB_GetSelectedItems (universal)
Code:
Copy      Help
;/
function hlb ARRAY(str)&a

;Gets text of selected items in a multiple-selection listbox.


int i n=SendMessage(hlb LB_GETSELCOUNT 0 0)
if(n=-1) ;;single-sel control
,a.redim(1)
,if(LB_SelectedItem(hlb a[0])<0) a.redim
else
,a.redim(n)
,if(n)
,,ARRAY(int) selitems.create(n)
,,SendMessage(hlb LB_GETSELITEMS n &selitems[0])
,,for(i 0 n) LB_GetItemText hlb selitems[i] a[i]
#6
Another example
Code:
Copy      Help
ARRAY(str)- t_af

str controls = "6 3 8"
str e6 lb3 e8
e6="$desktop$"
if(!ShowDialog("Dialog35" &Dialog35 &controls)) ret

e6.expandpath
int i
for(i 0 t_af.len) t_af[i].from(e6 "\" t_af[i])
out t_af

Function Dialog35
Code:
Copy      Help
;\Dialog_Editor
function# hDlg message wParam lParam

;BEGIN DIALOG
;0 "" 0x90C80A44 0x100 0 0 223 172 "Dialog"
;5 Static 0x54000000 0x0 4 4 40 13 "Folder"
;6 Edit 0x54030080 0x200 46 4 174 14 ""
;9 Button 0x54032000 0x0 202 20 18 14 "..."
;7 Static 0x54000000 0x0 4 20 40 13 "File pattern"
;8 Edit 0x54030080 0x200 46 20 112 14 ""
;3 ListBox 0x54230109 0x200 4 38 216 114 ""
;1 Button 0x54030001 0x4 60 156 48 14 "OK"
;2 Button 0x54030000 0x4 112 156 48 14 "Cancel"
;END DIALOG
;DIALOG EDITOR: "" 0x2020100 "" ""


;messages
sel message
,case WM_INITDIALOG
,SetTimer hDlg 1 100 0
,case WM_DESTROY
,case WM_COMMAND goto messages2
,case WM_TIMER
,sel wParam
,,case 1
,,KillTimer hDlg 1
,,int hlb=id(3 hDlg)
,,SendMessage hlb LB_RESETCONTENT 0 0
,,str sf.getwintext(id(6 hDlg)) sp.getwintext(id(8 hDlg))
,,if(sf.len)
,,,sf.from(sf "\" iif(sp.len sp "*"))
,,,Dir d
,,,foreach(d sf FE_Dir)
,,,,SendMessage hlb LB_ADDSTRING 0 d.FileName
ret
;messages2
sel wParam
,case [EN_CHANGE<<16|6,EN_CHANGE<<16|8]
,SetTimer hDlg 1 1000 0
,
,case 9 ;;...
,str sm=
;;/dontrun /expandfolders 0x39 0
;Desktop ":: "
;C: "c:\"

,if(DynamicMenu(sm "" 1))
,,qm.GetLastSelectedMenuItem 0 &sf 0
,,sf.expandpath(sf 2)
,,sf.setwintext(id(6 hDlg))
,
,case IDOK
,ARRAY(str)- t_af
,LB_GetSelectedItems id(3 hDlg) t_af
,case IDCANCEL
ret 1
#7
As always, you are the best.
Thanks,
Stuart
#8
Hi Gintaras,
I finally got a chance to work with the examples you gave me. Usually I can reverse engineer to what I need. I am having a little more difficulty this time. Hope you can help but I understand if too involved!

Here is what I am trying to do:

In this particular applications screen, there is a listbox like this:

Code:
Copy      Help
Acc a=acc("" "LIST" win("Sample App" "WindowsForms10.Window.8.app.0.378734a") "WindowsForms10.SysListView32.app.0.378734a" "" 0x1000)

It has many entry lines of this type:


Code:
Copy      Help
Acc a=acc("" "LISTITEM" win("Sample App" "WindowsForms10.Window.8.app.0.378734a") "WindowsForms10.SysListView32.app.0.378734a" "sample value " 0x1404)

Each line has a different value. In that value is a record number which I am trying to extract.

Right now I go down that list serially using a "next" navigation statement.
Since the length of the list is variable ~5 to 100, it would be much better if I could have the user select-highlight (using Ctrl-left click or Shift-left click - like normal Windows functionality) the desired entries, and then have only those get acted upon.

Ctrl-Left click and Shift-left click already work to highlight this list in the desired fashion, bu my macro currently just goes from the top to the bottom, using additional (n1, n2, n3, n4)navigation steps.

Is it possible to extract this in a MultiSelect fashion or do I have to go through a dialog like in your examples?

I geuss another way would be for a QM macro to see which have already been multi-selected natively in the App and then use those as the signs to which to navigate and pull the Value from.

Sorry for long explanation. Hope you can help me.

Thanks,
Stuart
#9
Did you try Acc.Selection?

Code:
Copy      Help
Acc a=acc("" "LIST" ...)
ARRAY(Acc) se
a.Selection(se)
int i
for i 0 se.len
,str v=se[i].Value
,out v
#10
Worked Great!
Thanks a million
Stuart
#11
Code:
Copy      Help
str accession
Acc a=acc("" "LISTITEM" win("Sample App" "WindowsForms10.Window.8.app.0.378734a") "WindowsForms10.SysListView32.app.0.378734a" "" 0x1408 0 0 ""); err ret

ARRAY(Acc) se
a.Selection(se)
int arraylength=se.len
ARRAY(str) accessionarray.create(arraylength)

int i
for i 0 se.len
,str v=se[i].Description
,findrx(v "\d{8}" 2 4 accession)
,out i    
,out accession
,accessionarray[i]=accession
,


int choice
if(!inp(choice "" "" "Enter number of choice")) ret
out choice
out accessionarray[choice]


I don't know much about ARRAYS so I had to kind of reverse engineer some examples. Apparently you have to define the size each time ahead of time, so that's what I did with
code]ARRAY(str) accessionarray.create(arraylength)[/code]
Is thatt right?
Anyway it seems to be working.


Thanks so much!!!
Stuart
#12
If I want to select the whole list automatically instead of user input, I can "extend selection" from first acc object to last acc object but I need to know the total number to do that. How can I get the total number of child windows of a given acc (the parent of the List Items)?

Thanks so much,
Stuart
#13
Code:
Copy      Help
Acc a=acc(...)
out a.a.ChildCount
#14
Hi Gintaras,
I am trying to get the 0-based index of all the selected items from a MULTISELECT LB.

I already know how to get the text of all the selected items out using:
Quote:Function LB_GetSelectedItems (universal)

;/
function hlb ARRAY(str)&a

;Gets text of selected items in a multiple-selection listbox.


int i n=SendMessage(hlb LB_GETSELCOUNT 0 0)
if(n=-1) ;;single-sel control
,a.redim(1)
,if(LB_SelectedItem(hlb a[0])<0) a.redim
else
,a.redim(n)
,if(n)
,,ARRAY(int) selitems.create(n)
,,SendMessage(hlb LB_GETSELITEMS n &selitems[0])
,,for(i 0 n) LB_GetItemText hlb selitems[i] a[i]

and I know how to get the 0-based index from a single-select listbox using LB_SelectedItem but not from a multiselect.

The LB_GetSelectedItems function seems to get them all out in one go via LB_GETSELITEMS so that i counter-variable doesn't refer to the original array index but the newly filled index of JUST the selected items.

Is there any way to extract an array of selected index positions rather than text?

Thanks!!!!, Stuart
#15
In your code, selitems is that array.
#16
of course. :oops: ..thanks so much!!!!!

Here is a "new function" based on that realization:

Function LB_GetSelectedItemsIndexArray
Code:
Copy      Help
;/
function hlb ARRAY(int)&selitems

;Gets integer array of selected items 0-based index in a multiple-selection listbox.


int i n=SendMessage(hlb LB_GETSELCOUNT 0 0)
if(n)
,selitems.create(n)
,SendMessage(hlb LB_GETSELITEMS n &selitems[0])


Thanks again, Stuart
#17
@[b]Gintaras[/b]

I tested the example above, enumerating the files on the desktop, and displaying garbled characters in the list.


Attached Files Image(s)
   
#18
I have selected unicode in the dialog and QM option settings.


Forum Jump:


Users browsing this thread: 4 Guest(s)