News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Getting the name and location of selected file from FileMenu (Context Menu)

Started by LiaoMi, August 19, 2017, 08:51:11 PM

Previous topic - Next topic

LiaoMi

Hello!

I would like to automate copying of all files in one document. Usually for files I use Copy /b  name.txt name1.txt name2.txt Combined.txt on the command line. But Im tired of doing it manually, so Id like to add the "Merge to one text file" command in the context of the selected files. To do this, I need to get the names of the selected files, the question is how to do it better? GetOpenFileName function is not very suitable for this task. How can i get selected files in Windows Explorer using WinApi functions ?!

Best regards


aw27

Quote from: LiaoMi on August 19, 2017, 08:51:11 PM
How can i get selected files in Windows Explorer using WinApi functions ?!

A little involving from ASM, but a piece of cake for the script kiddies.  ;)


hutch--

You need to create a new file and keep appending the rest to it. Depending on what the file names are, you could do a *.* type file pattern for say "all TXT files" in a directory with "*.txt" or any predictable combination.

The API calls are FindFirstFile and FindNextFile.

jj2007

Isn't Windows simple and easy to use?
Get selected items of folder with WinAPI

However, you could throw the attached exe into the SendTo folder. Here is the source; GetFiles CL translates the dragged files into a string array:

include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  Let esi="Files_"+Replace$(fDate$(0), ".", 0))
  Let esi=esi+"_"+Replace$(fTime$(0), ":", 0)+".txt"  ; e.g. Files_190817_155907.txt
  GetFiles CL
  ; SortFiles                           ; activate to put most recent first
  For_ ecx=0 To Min(99, eax-1)
        PrintLine Str$(GfSize(ecx)), Tb$, GfDate$(ecx), Spc2$, GfTime$(ecx), Tb$, Files$(ecx)
  Next
  void Str$("Combine %i files to single file:", Files$(?))
  Let esi=Input$(eax, esi)
  .if Instr_(esi, ".")
        PrintLine Str$("writing %i textfiles to ", Files$(?)), esi
        Open "O", 1, esi
        For_ ecx=0 To Files$(?)-1
                mov edi, Files$(ecx)
                Print 1, FileRead$(edi), CrLf$, String$(40, "-."), CrLf$        ; decoration added ;-)
        Next
        Close
        Inkey "See the result (y)?"
        If_ eax=="y" Then ShEx esi
  .else
        Print "CANCELLED"
        Delay 2000
  .endif
EndOfCode


For easy testing, the attached source has OPT_Arg1 with three Masm32 SDK files. Of course, the -.-.-. decoration should be taken away if you don't need it. As usual, dragging true Unicode filenames is allowed, see screenshot below. "Invia a" is "Send to" in Italian.

LiaoMi

Quote from: hutch-- on August 19, 2017, 10:49:30 PM
You need to create a new file and keep appending the rest to it. Depending on what the file names are, you could do a *.* type file pattern for say "all TXT files" in a directory with "*.txt" or any predictable combination.

The API calls are FindFirstFile and FindNextFile.

This is an alternative solution for the command line, you can drag and drop on the exe, getting all the names and then doing the merging. The question is how to get names!

Quote from: jj2007 on August 19, 2017, 10:55:14 PM
Isn't Windows simple and easy to use?
Get selected items of folder with WinAPI

Very interesting, I think that a bit tricky solution.

Quote from: jj2007 on August 19, 2017, 10:55:14 PM

However, you could throw the attached exe into the SendTo folder. Here is the source; GetFiles CL translates the dragged files into a string array:

include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  Let esi="Files_"+Replace$(fDate$(0), ".", 0))
  Let esi=esi+"_"+Replace$(fTime$(0), ":", 0)+".txt"  ; e.g. Files_190817_155907.txt
  GetFiles CL
  ; SortFiles                           ; activate to put most recent first
  For_ ecx=0 To Min(99, eax-1)
        PrintLine Str$(GfSize(ecx)), Tb$, GfDate$(ecx), Spc2$, GfTime$(ecx), Tb$, Files$(ecx)
  Next
  void Str$("Combine %i files to single file:", Files$(?))
  Let esi=Input$(eax, esi)
  .if Instr_(esi, ".")
        PrintLine Str$("writing %i textfiles to ", Files$(?)), esi
        Open "O", 1, esi
        For_ ecx=0 To Files$(?)-1
                mov edi, Files$(ecx)
                Print 1, FileRead$(edi), CrLf$, String$(40, "-."), CrLf$        ; decoration added ;-)
        Next
        Close
        Inkey "See the result (y)?"
        If_ eax=="y" Then ShEx esi
  .else
        Print "CANCELLED"
        Delay 2000
  .endif
EndOfCode


For easy testing, the attached source has OPT_Arg1 with three Masm32 SDK files. Of course, the -.-.-. decoration should be taken away if you don't need it. As usual, dragging true Unicode filenames is allowed, see screenshot below. "Invia a" is "Send to" in Italian.

Very cool :icon_exclaim:, I didnt think about the SendTo option, and the Hutch solution will work too. Meanwhile, I was advised to look at the source 7zip https://sourceforge.net/projects/sevenzip/files/7-Zip/17.00/7z1700-src.7z/download Since the program registers the Schell Extension to receive files for compression. Most likely the method is more massive, not as simple as with SendTo. I have not yet found the code responsible for this processing. jj2007 thanks, with the source code, everything is ready, just like a mega service! :redface: It is very convenient now to work with files.

hutch--

It very much depends on how you wish to access the file names, large numbers with predictable extensions OR filename parts are best done from the command line but if you want a UI, then you will be dragging and dropping the files into an interface where the names are accumulated in the order they are dropped unless you want to sort the name list. A list box would be very useful in this context, whatever is dropped into the interface gets added to the list box.

aw27

I have another Sendto solution:
Make a batch file:

echo off
for %%i in (%*) do type "%%~i">>c:\combined.txt

give it a name and copy it to the Sendto folder.

:badgrin:

aw27

Improved Sendto batch file, which accepts destination name:

@echo off
setlocal EnableDelayedExpansion
set mycommand=copy
for %%i in (%*) do (
    set mycommand=!mycommand! "%%i" +
)
set /p dest="Enter destination file: "
set mycommand=!mycommand:~0,-2! %dest%
!mycommand!

hutch--

If it can be done by a user specified file pattern on the command line and it is a text based file, it can be done like this.

Just read back and its very similar to AW's 1st suggestion.


@echo off

:::: %1 is a command line file pattern -> *.txt
:::: %2 is the target file name for the result.

for %%9 in (%1) do type %%9 >> %2

pause


Useage like this.

MyBatch *.txt combined.txt

jj2007

Quote from: hutch-- on August 20, 2017, 12:56:07 AMA list box would be very useful in this context, whatever is dropped into the interface gets added to the list box.

Right :t

GuiParas equ "Combine text files: drag files to add", x50, y50, w300, h600     ; OPT_Icon Disk
include \masm32\MasmBasic\Res\MbGui.asm
invoke SetWindowPos, hWnd, HWND_TOPMOST, eax, eax, eax, eax, SWP_NOMOVE or SWP_NOSIZE

SetGlobals dest$, item$
GuiControl Edit, "edit", "~TmpFile.txt", h0+20, w800
GuiControl Ok, "button", "ok", h0+20, x800, w200
GuiControl MyBox, "listbox", y0+22, h1000-22
Let item$=New$(1000)   ; event dropfiles yields UTF8, so we'll be generous

Event Menu
  .if MenuID==Ok
        Let dest$=Win$(hEdit)
        MsgBox 0, Cat$("Copy files into"+CrLf$+dest$), "Hi", MB_YESNO
        .if eax==IDYES
                Open "O", #1, dest$
                Print #1, Utf8Bom
                For_ ct=0 To rv(SendMessage, hMyBox, LB_GETCOUNT, 0, 0)-1
                 invoke SendMessage, hMyBox, LB_GETTEXT, ct, item$
                 Print #1, FileRead$(item$), CrLf$, String$(40, "-."), CrLf$      ; decoration added ;-)
                Next
                Close
                MsgBox 0, Cat$("Open "+dest$+" in the default application?"), "Hi", MB_YESNO
                If_ eax==IDYES Then ShEx dest$
        .endif
  .endif

Event DropFiles
  SetListbox Files$()

GuiEnd


Note there is a limit somewhere, AFAIK 32k for the total amount of paths passed while dragging.

LiaoMi

Hello,

thanks for the very elegant solutions, these methods are the simplest among others, which I also found, even a batch file is enough  :t

Getting the current selection from an Explorer window https://blogs.msdn.microsoft.com/oldnewthing/20130422-00/?p=4593
Querying information from an Explorer window https://blogs.msdn.microsoft.com/oldnewthing/20040720-00/?p=38393

I wish everyone a good Sunday  :exclaim: