1272 / 973 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
1

Как программно эмулировать Drag&drop файла на окно стороннего приложения

11.09.2012, 02:52. Показов 2489. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
ну собственно вопрос в названии
к окну никакого отношения не имею и оно не на net, просто найдено среди процессов

я думаю это какой нибудь PostMessage, но что туда передавать?
нашел что-то про WM_DROPFILES, но везде пишут про прием файла переданного обычным образом
не знаю даже за что зацепиться чтоб яндексить дальше

зачем
хочу сделать свою продвинутую автозагрзку внешних субтитров для видео проигрывателя, ничего кроме этого не придумал.
обычные средства не загружают из отдельных папок с левыми названиями типа группы переводчиков и т.д
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
11.09.2012, 02:52
Ответы с готовыми решениями:

Drag&Drop
Требуется сделать так, чтобы при перетаскивании файла в текстбокс, в этом текстбоксе появлялся...

Drag&Drop
Уважаемые коллеги, есть такая задача, на форму кидают файл, мне нужно получить его полное имя (путь...

Drag&Drop картинки
как сделать чтобы при перетаскивании картинки (например из мозилы), она сохранялась в переменную...

drag&drop из внешних приложений
привет. собственно как сделать сабж? например из проводника? у меня есть imageview, как перенести...

4
Почетный модератор
Эксперт .NET
8717 / 3669 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
12.09.2012, 01:03 2
Лучший ответ Сообщение было отмечено как решение

Решение

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
        const uint WM_DROPFILES = 0x233;
 
        [DllImport( "user32.dll", SetLastError = true, CharSet = CharSet.Unicode )]
        static extern int PostMessage (
            [In] IntPtr hWnd,
            [In] uint Msg,
            [In] IntPtr wParam,
            [In] IntPtr lParam
            );
 
        const uint GHND = 0x42;
 
        [DllImport( "kernel32.dll", SetLastError = true )]
        static extern IntPtr GlobalAlloc (
            [In] uint uFlags,
            [In] int dwBytes // for x86
            // [In] long dwBytes // for x64
            );
 
        [DllImport( "kernel32.dll", SetLastError = true )]
        static extern IntPtr GlobalFree (
            [In] IntPtr hMem
            );
 
        [DllImport( "kernel32.dll", SetLastError = true )]
        static extern IntPtr GlobalLock (
            [In] IntPtr hMem
            );
 
        [DllImport( "kernel32.dll", SetLastError = true )]
        [return: MarshalAs( UnmanagedType.Bool )]
        static extern bool GlobalUnlock (
            [In] IntPtr hMem
            );
 
        [DllImport( "kernel32.dll", SetLastError = true )]
        static extern int GlobalSize (
            [In] IntPtr hMem
            );
 
        [DllImport( "Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode )]
        unsafe static extern int DragQueryFile (
            [In] IntPtr hDrop,
            [In] int iFile,
            [Out] StringBuilder lpszFile,
            [In] int cch
            );
 
        [DllImport( "ntdll.dll", CallingConvention = CallingConvention.Cdecl )]
        unsafe static extern void* memcpy (
            [In] void* destination,
            [In] void* source,
            [In] int num // for x86
            // [In] long num // for x64
            );
 
        [StructLayout( LayoutKind.Sequential, Pack = 4 /* x86 */ )]
        struct DROPFILES
        {
            public int pFiles;
            public long pt;
            public int fNC;
            public int fWide;
        }
 
        unsafe IntPtr GetDropFilesPtr ( string[] files )
        {
            int memAllocSize = 0; // in bytes
            var dropFiles    = new DROPFILES();
            var pMem         = IntPtr.Zero;
            var pLockedMem   = IntPtr.Zero;
            var ptr          = (byte*)0;
 
            dropFiles.fWide = 1;
            dropFiles.pFiles = Marshal.SizeOf( dropFiles );
 
            for ( int i = 0; i < files.Length; ++i )
                memAllocSize += (files[i].Length * 2) + 2 /* \0\0 */;
            memAllocSize += 2; // \0\0
            memAllocSize += dropFiles.pFiles;
 
            pMem = GlobalAlloc( GHND, memAllocSize );
            pLockedMem = GlobalLock( pMem );
            {
                // copy files names to unmanaged mem
                *(DROPFILES*)(void*)pLockedMem = dropFiles;
                ptr = (byte*)pLockedMem + dropFiles.pFiles;
 
                for ( int i = 0; i < files.Length; ++i )
                {
                    int count = files[i].Length * 2;
                    fixed ( char* pBuff = files[i] )
                        memcpy( ptr, pBuff, count );
                    ptr += count + 2;
                }
            }
 
            if ( !GlobalUnlock( pMem ) && Marshal.GetLastWin32Error() != 0 )
            {
                GlobalFree( pMem );
                pMem = IntPtr.Zero;
            }
 
            return pMem;
        }
 
        unsafe private void button1_Click ( object sender, EventArgs e )
        {
            var ptr = GetDropFilesPtr(
                new string[] {
                    @"E:\Downloads\Video\SomeVideoFile.mkv"
                } );
            //var pointer = GlobalLock( ptr );
            var ret = PostMessage( (IntPtr)0x000E06F0 /* Main MPC window */, WM_DROPFILES, ptr, IntPtr.Zero );
            //var sb = new StringBuilder( 256 );
            //var sz = DragQueryFile( pointer, 0, sb, sb.Capacity );
            //GlobalUnlock( pointer );
            System.Threading.Thread.Sleep( 100 );
            GlobalFree( ptr );
            ...
Проверял на MediaPlayerClassic, на x86 процессе.

Не по теме:

p.s. Во время написания кода было обнаружено странное поведение CLR при маршалинге структуры DROPFILES: если использовать тип bool (с атрибутом MarshalAs или без него) для полей fNC и fWide, то происходило некорректное изменение значений в памяти, вместо нужного 01 00 00 00 01 00 00 00 было 01 01 00 00 00 00 00 00 (под bool выделялось 4 байта), из-за этого некорректно отрабатывала DragQueryFile (строка воспринималась в ANSI кодировке).
Если кто знает причину такого поведения - прошу высказаться. (Заниматься исследованием вопроса сейчас нет ни времени, ни желания).

ADD: как вариант можно использовать FieldOffset, тогда всё ок. Если использовать просто bool тогда генерируются неправильные инструкции для данных полей, значения меняются в соседних ячейках памяти...

1
1272 / 973 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
12.09.2012, 02:01  [ТС] 3
офигенно, оно работает
ток пришлось добавить CallingConvention.Cdecl для memcpy, иначе он разбалансировал стек

p/s если кто потом использовать надумает - передавайте в PostMessage хендл контрола, а не окна, взять его можно в spy++
1
Почетный модератор
Эксперт .NET
8717 / 3669 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
12.09.2012, 02:08 4
Цитата Сообщение от m0nax Посмотреть сообщение
ток пришлось добавить CallingConvention.Cdecl для memcpy, иначе он разбалансировал стек
Да, забыл Поправил.
0
1272 / 973 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
12.09.2012, 02:31  [ТС] 5
p/s если кто потом использовать надумает - передавайте в PostMessage хендл контрола, а не окна, взять его можно в spy++
это я погорячился, передавать как раз хендл окна либо контрола, не хендл процесса главное, короче process.MainWindowHandle сработал и пока что все обошлось без поиска конкретных контролов в окне
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.09.2012, 02:31
Помогаю со студенческими работами здесь

Drag & Drop динамически созданных объектов
Научите пожалуйста как осуществить сабж, в разделе для новичков не помогли Создаю в...

Как проверить открыто ли окно стороннего приложения?
Я не знаю как написать программу, которая бы проверяла (т.е. if окно в фокусе then), помогите, мне...

Вывод текста в окно стороннего приложения
Подскажите есть игра и в ней нужно по координатам вывести текст или что нибудь нарисовать. Какими...

Клик в свернутое окно стороннего приложения
Вообщем, мне нужно сделать клик в форму которая свернутая. Например Skype. Он у меня свернутый а...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru