Конференция "KOL" » Как получить имена выделенных файлов [Delphi, Windows]
 
  • RusSun © (01.06.10 20:58) [0]
    Доброе время суток.
    Как получить имена выделенных файлов? На рабочем столе есть "куча" созданных файлов одного типа. Выделяем курсом чтобы в дальнейшем объединить их в один файл.
  • RusSun © (03.06.10 18:21) [1]
    Имеется ввиду не drag and drop. А именно Выделение и нажатие клавиши. "Остальное дело техники".
  • RusSun © (03.06.10 21:35) [2]
    И формы тоже нет только applet. Эх никого нет чтоб толковый дать совет.:(
  • RusSun © (08.06.10 20:25) [3]
    Доброе время суток. По порядку.

    Чтобы получать файлы используют функцию  DragQueryFile модуля ShellAPI.
    получилось следующие:
    1. копируем файлы *.txt в буфер обмена
    2. переходим в applet
    3. жмем клавишу "O" и получаем общий  файл tst.txt

    вот код:

    program Project1;

    uses
     windows,messages,
     kol,shellapi;     //,clipbrd

    {$R *.res}
    var SL: PStrList;S:String;

    //Для функции
    function file2str(filename:string):string;
    var f2: textfile;
       s2:string;
    begin
      result := '';
      if fileexists(filename) then
      begin
          S2:='';
          assignfile(f2,filename);
          reset(f2);
          while not eof(f2) do
          begin
             readln(f2,s2);
             result := result + s2+#13#10;//с переходом на другую строку
          end;
          closefile(f2);
        end;
    End;
    //область для процедур
    procedure unitetextfiles(Dummy : Pointer; Sender: PControl; var Key: Integer;
    Shift: Cardinal);
    var
    f: THandle;
    buffer: array [0..MAX_PATH] of Char;
    i, numFiles: Integer;
    begin

    if key=27 then applet.Close;//Esc выход
    if key=79  then begin //showmessage(' копируем файлы в буфер ');  //or
                   SL := NewStrList;
    if not OpenClipboard( Applet.GetWindowHandle ) then Exit;
    OpenClipboard(0);
    try
    if IsClipboardFormatAvailable( CF_HDROP )then
    f := GetClipboardData(CF_HDROP);
    if f <> 0 then
      begin
        numFiles := DragQueryFile(f, $FFFFFFFF, nil, 0);
        S:='';
       // for i :=0 to numfiles - 1  do
        for i :=numfiles - 1  downto 0 do
        begin
          buffer[0] := #0;
          DragQueryFile(f, i, buffer, SizeOf(buffer));
          S:=s + file2str(buffer);//+#13#10 сплошное
          //S:=s + file2str(buffer)+#13#10; с разделителем строка
          //S:=s + buffer+#13#10;
        end;
      end;
      SL.Text := S;

      SL.SaveToFile( 'tst.txt' );
      SL.Free;
    finally
      CloseClipboard;
    end;
    end
    end;
    Begin
    //.centeronparent.Tabulate;
    //область для работы
    Applet := NewApplet( 'Unite text'+#39+'s ' );
    applet.OnKeyDown := TOnKey( MakeMethod( nil, @unitetextfiles ) );
    Run(Applet);
    end.


    Два не больших вопроса.
    Можно ли отправлять выделенные файлы на рабочем столе из программы в буфер обмена программно?
    Второй вопрос: Хотел сделать горячую клавишу вместо кеydown
    взял пример в мск он работает, а в кол почему-то нет. Как поправить?
    пример:

    program Project1;

    uses
     windows,messages,
     kol;
    type  TOnEvent = procedure( Sender: PObj )of object;
    {$R *.res}
    var
    form:PControl;

    //область для процедур
    function FormMessage(Dummy : Pointer;var Msg: tagMSG; var Rslt: Integer): Boolean;
    begin
    case Msg.message of
     WM_HOTKEY:
     begin
       case Msg.wParam of
         1:Form.Visible:=false;
         2:Form.Visible:=true;
       end;
     end;
    end;//case
    Result := False;
    end;

    procedure FormClose(Dummy : Pointer; Sender: PControl; var Accept: Boolean);
    begin
    UnRegisterHotkey(form.Handle, 1);
    UnRegisterHotkey(form.Handle, 2);
    end;

    Begin
    form:=NewForm(Applet,'hot key').SetSize(300,200).setposition(330,300);
    //.centeronparent.Tabulate;

    //область для работы
    form.OnMessage:=TOnMessage(MakeMethod(nil,@FormMessage));
    form.OnClose:=TOnEventAccept(MakeMethod(nil,@FormClose));

    RegisterHotkey(form.Handle, 1, MOD_ALT or MOD_SHIFT, VK_F4);
    RegisterHotkey(form.Handle, 2, MOD_ALT or MOD_SHIFT, VK_F5);
    applet:=form;
    Run(applet);
    end.

  • Vladimir Kladov © (09.06.10 08:05) [4]
    Можно ли отправлять выделенные файлы на рабочем столе из программы в буфер обмена программно?
    ----------------------------------
    Ответ: можно. Добраться до окна SHELLDLL_DefView - это окно - родитель листвью рабочего стола, ЕМНИП. В общем, погуглите. Много примеров на бэйсике попадается, разобраться можно. Ну, с листвью как работать, надеюсь, объяснять не надо.

    Второй вопрос: Хотел сделать горячую клавишу вместо кеydown
    взял пример в мск он работает, а в кол почему-то нет. Как поправить?
    ===========================
    Список параметров неполный у обработчика. Dummy, затем Sender, потом все остальное.
  • RusSun © (09.06.10 16:53) [5]
    Доброе время суток.

    function FormMessage(Dummy : Pointer;Sender: PControl;var Msg: tagMSG; var Rslt: Integer): Boolean;


    Вызывает "access violation at ... : read of address ... . "

    Спасибо, погуглим.
  • RusSun © (09.06.10 17:19) [6]
    Уточняю: Kol_ASM.inc
    function TControl.WndProc( var Msg: TMsg ): Integer;
    ...
    RET строка 8347 +F7

    "access violation at ... : read of address ... . "
  • RusSun © (11.06.10 18:32) [7]
    Доброе время суток.
    Нашел почему не работает. Кстати Sender: PControl; оказался не причём
    вот без этого не работает уж не знаю почему:) -> .centeronparent
    то есть
    form:=NewForm(Applet,'hot key').SetSize(300,200).centeronparent;

  • Vladimir Kladov © (12.06.10 00:01) [8]
    CenterOnParent вызывает создание окна для формы, т.к. центрировать он может только окно с хэндлом. Намек ясен?
  • RusSun © (18.06.10 19:10) [9]
    Доброе время суток.
    Вот такой вопрос.

    нашел как передавать названия файлов выделенных на рабочем столе
    на примере с memo.

    вариант vcl: http://slil.ru/29356827
    и
    кол:
    program Project1;

    uses
     windows,
     kol;

    {$R *.res}
    var
    form,Button,Memo:PControl;

    //область для функции
    function GetDesktopListViewHandle: THandle;
    var
     S: string;
    begin
     Result := FindWindow('ProgMan', nil);
     Result := GetWindow(Result, GW_CHILD);
     Result := GetWindow(Result, GW_CHILD);
     SetLength(S, 40);
     GetClassName(Result, PChar(S), 39);
     if PChar(S) <> 'SysListView32' then
       Result := 0;
    end;

    //ItemCount
    function ListView_GetItemCount(hWnd: HWND): Integer;
    begin
    Result := SendMessage(hWnd, LVM_GETITEMCOUNT, 0, 0);
    end;

    //SelectedCount
    function ListView_GetSelectedCount(hwndLV: HWND): UINT;
    begin
     Result := SendMessage(hwndLV, LVM_GETSELECTEDCOUNT, 0, 0);
    end;

    //область для процедур
    procedure clickbutton(Sender:PControl; var mouse:TMouseEventData);
    var
       process: Cardinal;
      r : TRect;
      hWnd : THandle;
      Count, selcount : Integer;
     I: Integer;
     txt : String;
       _Item: PKOL_Char;
       lvi: TLVITEM;
       _lvi: PLVITEM;
       pid: longint;
       Written: dword;
    begin
     Memo.Clear;
     hWnd := GetDesktopWindow();
     GetWindowRect(hWnd,r);
     Memo.Add('Bottom: ' +  Int2Str(r.Bottom)+#13#10);
     Memo.Add('Right: ' + Int2Str(r.Right)+#13#10);

     hWnd := GetDesktopListViewHandle;
     Count := ListView_GetItemCount(hWnd);
     selCount:=ListView_GetSelectedCount(hwnd);
     Memo.Add('Total icons: ' + Int2Str(Count)+#13#10);
     Memo.Add(''+#13#10);
     if selCount=0 then  Memo.Add('NoSelected icons: '+#13#10) else
     Memo.Add('Selected icons: ' + Int2Str(selCount)+#13#10);

     GetWindowThreadProcessId(hwnd, @pid);
     process:=OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or
                        PROCESS_VM_WRITE or PROCESS_QUERY_INFORMATION, FALSE, pid);

     _lvi:=VirtualAllocEx(process, nil, sizeof(TLVITEM),MEM_COMMIT, PAGE_READWRITE);
     _item:=VirtualAllocEx(process, nil, 255, MEM_COMMIT,PAGE_READWRITE);
     SetLength(txt, 255);
     lvi.cchTextMax:=255;

     for i:=0 to count-1 do
     if BOOL(SendMessage(hWnd, LVM_GETITEMSTATE, i, LVIS_SELECTED)) then
     begin
       lvi.iSubItem:=0;
       lvi.pszText:=_item;
       WriteProcessMemory(process, _lvi, addr(lvi), sizeof(TLVITEM), Written);  // <- здесь ругается
       SendMessage(hwnd, LVM_GETITEMTEXT, wParam(i), lParam(_lvi));
       ReadProcessMemory(process, _item, PChar(txt), 255, Written);
       memo.Add(txt) //+#13#10
     end;
    end;

    Begin
    form:=NewForm(Applet,'Dectop to memo').SetClientSize( 406, 252 ).centeronparent;
    //.Tabulate;

    Button := NewButton( form, 'Список' ).SetPosition( 230,6 );
    Memo := NewEditBox( form, [ eoMultiline, eoNoHScroll ] ).SetPosition( 8,38 ).SetClientSize( 377, 200);
    Memo.Color := clWindow;
    Memo.Text := '';
    //область для работы
    Button.OnClick:=TonEvent(MakeMethod(nil,@clickbutton));
    Run(form);
    end.



    код одинаковый, но в кол почему то после нахождения
    1 выделенного добавление в memo прекращается  :)
    Чего не хватает чтобы работало нормально?
  • MTsv DN (18.06.10 23:51) [10]
    Отслеживай переменные. Правка:
    memo.Add(Trim(txt) + #13#10)

  • RusSun © (19.06.10 07:06) [11]
    Теперь нормально, работает:)
    2MTsv DN Спасибо!
  • RusSun © (28.06.10 22:15) [12]
    Доброе время суток.
    Вот такой вопрос. Пытаюсь в примере используя
    пути к файлам объединить их в один.
    Вот через буфер обмена всё работает, а вот
    через пути без буфера не хочет не пойму в чём загвоздка?
    вот код:
    program Project1;

    uses
     windows,messages,
     kol,shellapi;    

    {$R *.res}
    var SL: PStrList;S,s3:String;

    //область для функции

    function GetDesktopListViewHandle: THandle;
    var
     S: string;
    begin
     Result := FindWindow('ProgMan', nil);
     Result := GetWindow(Result, GW_CHILD);
     Result := GetWindow(Result, GW_CHILD);
     SetLength(S, 40);
     GetClassName(Result, PChar(S), 39);
     if PChar(S) <> 'SysListView32' then
       Result := 0;
    end;
    //ItemCount
    function ListView_GetItemCount(hWnd: HWND): Integer;
    begin
    Result := SendMessage(hWnd, LVM_GETITEMCOUNT, 0, 0);
    end;
    //SelectedCount
    function ListView_GetSelectedCount(hwndLV: HWND): UINT;
    begin
     Result := SendMessage(hwndLV, LVM_GETSELECTEDCOUNT, 0, 0);
    end;

    function file2str(filename:string):string;
    var f2: textfile;
       s2:string;
    begin
      result := '';
      if fileexists(filename) then
      begin
          S2:='';
          assignfile(f2,filename);
          reset(f2);
          while not eof(f2) do
          begin
             readln(f2,s2);
             result := result + s2+#13#10;//с переходом на другую строку
          end;
          closefile(f2);
        end;
    End;

    function FormMessage(Dummy : Pointer;var Msg: tagMSG; var Rslt: Integer): Boolean;
    begin
    case Msg.message of
     WM_HOTKEY:
     begin
       case Msg.wParam of
         1:Applet.Visible:=false;
         2:Applet.Visible:=true;
       end;
     end;
    end;//case
    Result := False;
    end;

    function sysvar_2_folder(sysvar :String) :String;
    var buf : array[0..$FF]
    of char; Size : integer;
    begin
    Size := ExpandEnvironmentStrings(PChar(sysvar), buf, sizeof(buf));
    Result := copy(buf, 1, Size);
    end;

    //область для процедур
    procedure unitetextfiles(Dummy : Pointer; Sender: PControl; var Key: Integer;
    Shift: Cardinal);
    var
       process: Cardinal;
      hWnd : THandle;
      Count, selcount : Integer;
     I: Integer;
     txt : String;
       _Item: PKOL_Char;
       lvi: TLVITEM;
       _lvi: PLVITEM;
       pid: longint;
       Written: dword;
    begin

    if key=27 then applet.Close;//Esc выход
    if key=79  then begin
    s:='';
    hWnd := GetDesktopListViewHandle;
    Count := ListView_GetItemCount(hWnd);
    selCount:=ListView_GetSelectedCount(hwnd);
     if selCount=0 then  s3:=s3+' NoSelected icons: '+#13#10 else
     s3:=s3+' Selected icons: ' + Int2Str(selCount)+#13#10;
     SL := NewStrList;
     GetWindowThreadProcessId(hwnd, @pid);
     process:=OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or
                        PROCESS_VM_WRITE or PROCESS_QUERY_INFORMATION, FALSE, pid);

     _lvi:=VirtualAllocEx(process, nil, sizeof(TLVITEM),MEM_COMMIT, PAGE_READWRITE);
     _item:=VirtualAllocEx(process, nil, 255, MEM_COMMIT,PAGE_READWRITE);
     SetLength(txt, 255);
     lvi.cchTextMax:=255;

     for i:=0 to count-1 do
     if BOOL(SendMessage(hWnd, LVM_GETITEMSTATE, i, LVIS_SELECTED)) then
     begin
       lvi.iSubItem:=0;
       lvi.pszText:=_item;
       WriteProcessMemory(process, _lvi, addr(lvi), sizeof(TLVITEM), Written);  // <- здесь ругается
       SendMessage(hwnd, LVM_GETITEMTEXT, wParam(i), lParam(_lvi));
       ReadProcessMemory(process, _item, PChar(txt), 255, Written);
    SL.Text:=SL.Text+file2str(sysvar_2_folder('%USERPROFILE%\Рабочий стол\'+Trim(txt)+'.txt'#13#10));
                     end;
      SL.SaveToFile( 'tst.txt' );
      SL.Free;
      end;
    end;

    procedure FormClose(Dummy : Pointer;Sender: PControl; var Accept: Boolean);
    begin
    UnRegisterHotkey(Applet.Handle, 1);
    UnRegisterHotkey(Applet.Handle, 2);
    end;

    Begin
    //.centeronparent.Tabulate;
    //область для работы
    Applet := NewApplet( 'Unite text'+#39+'s ' ).centeronparent;
    applet.OnKeyDown := TOnKey( MakeMethod( nil, @unitetextfiles ) );
    Applet.OnMessage:=TOnMessage(MakeMethod(nil,@FormMessage));
    Applet.OnClose:=TOnEventAccept(MakeMethod(nil,@FormClose));

    RegisterHotkey(Applet.Handle, 1, MOD_ALT or MOD_SHIFT, VK_F4);
    RegisterHotkey(Applet.Handle, 2, MOD_ALT or MOD_SHIFT, VK_F5);
    Run(Applet);
    end.


    и в tst.txt в итоге 0. Хотя должен быть текст.
  • Дмитрий К © (29.06.10 00:38) [13]
    В sysvar_2_folder фигню передаете.
  • RusSun © (29.06.10 04:58) [14]

    > Дмитрий К ©   (29.06.10 00:38) [13]
    >
    > В sysvar_2_folder фигню передаете.


    Путь в sysvar_2_folder получается, но дальше ничего не идёт.
    то бишь
    sysvar_2_folder('%USERPROFILE%\Рабочий стол\'+Trim(txt)+'.txt'#13#10)
    даёт пути к файлам с именами и расширением.

    C:\Documents and Settings\Семья.D179777B4E904BC\Рабочий стол\файл1.txt
    C:\Documents and Settings\Семья.D179777B4E904BC\Рабочий стол\файл2.txt
    ...
    C:\Documents and Settings\Семья.D179777B4E904BC\Рабочий стол\27.txt
    пытаюсь передать путь file2str(filename:string):string и 0
  • Vladimir Kladov © (29.06.10 06:47) [15]
    Пошаговая отладка с остановкой на проблемной строчке и просмотром содержимого переменных спасет.
  • RusSun © (29.06.10 16:52) [16]
    Спасибо, с чуток покапавшись получил следующее:

    sysvar_2_folder('%USERPROFILE%') + '\Рабочий стол\' + Trim(txt);


    Правда на моем компе почему-то не кактит такой вариант, нужен

    sysvar_2_folder('%USERPROFILE%')+'\Рабочий стол\'+Trim(txt)+'.txt'



    #13#10 это почему-то ему не нравится?
    Всем Спасибо.
  • Vladimir Kladov © (29.06.10 17:10) [17]
    +'.txt'
    - вот это не знаю, для чего нужно у вас, но у меня приводит к тому, что далее проверка на FileExists всегда возвращает false, и то, что написано внутри if, никогда не отрабатывает.
  • RusSun © (29.06.10 18:05) [18]
    На компьютере дома Trim(txt) даёт только название без расширения. Поэтому и приходится добавлять +'.txt'.
    На работе Trim(txt) работает также как и у Вас (файл сразу с расширением).
    Как учесть эту разницу?
  • Vladimir Kladov © (29.06.10 20:24) [19]
    Во-1, если программа компилируется (а не запускается только exeшник) на обеих машинах, то убедиться, что на обоих компьютерах версии kol.pas + kol_asm.inc совпадают.

    Во-2, убедиться, что значение переменной txt одинаковое.

    А вы, случайно, не .lnk-файлы выделяете? Когда выделен ярлык, то возвращается путь на файл ярлыка, но без расширения .lnk, тогда понятно, почему приходится добавлять левое расширение.

    Но вот еще шютка, не знаю, то ли в семерке такая, то ли всегда: FileExists не работает, даже после исправления кода на
      SL.Text:=SL.Text+file2str(
         sysvar_2_folder('%USERPROFILE%\Рабочий стол\'+Trim(txt)))+#13#10;



    Мне это показалось странным, я создал текстовой документ, и посмотрел, что получается. Получается
    'C:\Users\Vlad\Рабочий стол\Новый текстовый документ.txt'

    Открываю проводник, начинаю идти по дереву с корня, он мне рисует
    C:\Users\Vlad\Desktop\...
    А если по дереву идти, то
    Локальный диск (C:) - Пользователи - Vlad - Рабочий стол ...
    Выделяю путь в адресной строке, он мне опять рисует с Desktop, вот такие пироги. Т.е. приплюсовывать надо на Рабочий стол, а Desktop. С Desktop работает, по крайней мере текст в tst.txt сбрасывается.
  • RusSun © (29.06.10 21:06) [20]
    1-oe проверю завтра.
    2-ое значение разное на разных машинах.
    Как то заметил. Вот на работе при создании файла также видно его расширение.
    Дома когда создаешь файл расширения нет просто вводишь имя и всё.



    > Но вот еще шютка, не знаю, то ли в семерке такая, то ли
    > всегда: FileExists не работает, даже после исправления кода
    > на
    >   SL.Text:=SL.Text+file2str(
    >      sysvar_2_folder('%USERPROFILE%\Рабочий стол\'+Trim(txt)))+#13#10;
    >
    >


    Уберите +#13#10 и будет работать
    SL.Text:=SL.Text+file2str(sysvar_2_folder('%USERPROFILE%\Рабочий стол\'+Trim(txt)));



    Нет файлы не линкованные. В моём случае действительно поведение именно такое.
    А Desktop в упор не воспринимает, только Рабочий стол.
  • Vladimir Kladov © (01.07.10 11:49) [21]
    Тогда или проверяйте версию системы, или делайте 2 попытки - одну для Desktop, другую для Рабочий стол. Надеюсь, программа предназначена только для русской системы (иначе, я даже не знаю, как называется рабочий стол в немецком, шведском, китайском, польском... языке).
  • QAZ (02.07.10 11:20) [22]

    > Вот на работе при создании файла также видно его расширение.
    > Дома когда создаешь файл расширения нет просто вводишь имя
    > и всё.

    панель управления->свойства папки->вид->скрывать расширения для зарегистрированых файлов

    > В моём случае действительно поведение именно такое.
    > А Desktop в упор не воспринимает, только Рабочий стол.

    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
    а там названия папок на любом языке

    ps
    с виндой для начала подружись хотябы на уровне пользователя
  • Vladimir Kladov © (02.07.10 15:43) [23]
  • RusSun © (02.07.10 19:40) [24]
    Доброе время суток!

    > Вот на работе при создании файла также видно его расширение.
    > Дома когда создаешь файл расширения нет просто вводишь имя
    > и всё.

    Уважаемый всё это было написано для того чтобы сказать что не чего от себя не придумал.  

    2QAZ

    > панель управления->свойства папки->вид->скрывать расширения
    > для зарегистрированых файлов
    >...
    > ps
    > с виндой для начала подружись хотябы на уровне пользователя


    А вопрос был такой как лучше сделать проверку скрыты расширения или нет чтобы не множить число программ для каждого случая :)

    2Vladimir Kladov
    Спасибо! прочитал.
  • RusSun © (02.07.10 21:12) [25]
    SHGetSpecialFolderPath(0,pchar(buff),CSIDL_DESKTOPDIRECTORY,true);
      S:=S+#13#10+file2str(pchar(buff)+'\'+Trim(txt)+'.txt');
    и
    SHGetSpecialFolderPath(0,pchar(buff),CSIDL_DESKTOPDIRECTORY,true);
      S:=S+#13#10+file2str(pchar(buff)+'\'+Trim(txt));
  • QAZ (02.07.10 22:51) [26]

    > http://www.transl-gunsmoker.ru/2008/12/shell-folders.html
    > - читать до конца.

    про шелфункции я в курсе
    а судя по [21] вы сами это только седня прочитали :)))


    > Уважаемый всё это было написано для того чтобы сказать что
    > не чего от себя не придумал.  
    > А вопрос был такой как лучше сделать проверку скрыты расширения
    > или нет чтобы не множить число программ для каждого случая
    > :)

    ага...
    а прозвучало как "почему на работе есть расширения а дома нет?"
    проверить можно через реестр, да ты и сам знаеш как...

    кстати примерчик ты нагуглил самый левый и работает он без гемора только потому что ты знаеш что работаеш с десктопом, а файлы *.тхт :)))
    при нормальной работе с шелом былобы пофиг показывает расширение или нет и в какой папке все это находится и файл ли это или папка и т.д.
  • RusSun © (03.07.10 11:32) [27]
    Принято. Спасибо.
    Какой был на тот момент такой и нагуглил;)
    Всем Спасибо:)))
 
Конференция "KOL" » Как получить имена выделенных файлов [Delphi, Windows]
Есть новые Нет новых   [120352   +28][b:0][p:0.006]