На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
  
> DragDrop файлов и самописный GUI , вид курсора
    всем привет.

    подскажите пожалуйста как решить задачу следующего типа.
    есть самописный gui, контролы рисуются на окне, т.е. окно верхнего уровня не имеет окон-чилдренов.
    добрался до драгдропа (WM_DROPFILES). и тут заметил неприятную штукенцию.

    например есть кнопка позволяющая кидать на себя файлы, естественно делаем топ-окну WS_EX_ACCEPTFILES.
    неприятность в том, что курсор принимает вид "можно бросить" в любом месте окна. Как сделать, чтобы курсор изменялся только находясь над кнопкой (не делая кнопку окном(HWND))?

    посоветуйте что-нибудь,
    спасибо :victory:
    Сообщение отредактировано: Emura -
      На ум приходит только сохранение региона(-ов), которые поддерживают Drag & Drop, ну и курсор естественно менять вручную, жестоко, но коли уж вся область одно окно с рисованной GUI, то и справляться явно придётся нестандартными методами.
        над подобным решением думал, но когда, например, хватаешь файл(ы) с рабочего стола и "машешь" над окном, окну сообщения вообще никакие не приходят..
          Emura, WS_EX_ACCEPTFILES тут не спасёт, да. Советую почитать про RegisterDragDrop.
          Сообщение отредактировано: Spawn.NET -
            ок, спасибо, посмотрю что за зверь.

            Spawn.NET, спасибо за помощь, работает. :good:
            Сообщение отредактировано: Emura -
              обнаружен при этом способе небольшой глючок в следующем.
              например,
              - кидаем папку из эксплорера в окно (IDropTarget).
              - обрабатываем файлы из папки(специфика программы).
              окно эксплорера (откуда бралась папка) подвисает на время обработки. подскажите пожалуйста куда смотреть. были варианты решения -пока тщетно.


              IDropTarget::Drop такого вида.

              IDropTarget::Drop()
              {
              извлекаем путь папки
              PostMessage с путем папки;
              }

              из функции успешно выходим перед тем как приходит сообщение от PostMessage, т.е. блокировать обработка не должна.. но блокировка налицо. :-?


              многопоточности нет, XP.

              тестовый проект
              ExpandedWrap disabled
                    
                 
                #include <windows.h>
                 
                 
                static const wchar_t* const gWindowClassName =L"-TEST_CLASS_NAME-";
                static const UINT WM_MAGIC =WM_APP + 0x4400;
                 
                 
                    static LRESULT CALLBACK gWindowProc( HWND h, const UINT message, const WPARAM wParam, const LPARAM lParam )
                    {
                 
                        switch ( message )
                        {
                        case WM_DESTROY:
                            {
                                ::PostQuitMessage(0);
                                return 0;
                                break;
                            }
                        case WM_MAGIC:
                            {
                                for ( int i=0; i<50; ++i )
                                {
                                    ::Sleep(100);
                                }
                                return 0;
                                break;
                            }
                        }
                 
                        return ::DefWindowProcW( h, message, wParam, lParam );
                 
                    };
                 
                 
                    class MyDropTarget : public IDropTarget
                    {
                    private:
                        ULONG       m_refCount;
                        HWND        m_owner;
                        wchar_t     m_data[1024];
                    public:
                        MyDropTarget( HWND owner ):
                          m_refCount    ( 1 ),
                              m_owner        ( owner )
                          {
                          }
                          virtual ~MyDropTarget()
                          {
                          }
                          HRESULT __stdcall QueryInterface( REFIID id, void FAR* FAR* result )
                          {
                              if ( id==IID_IUnknown ||
                                  id==IID_IDropTarget )
                              {
                                  *result =this;
                                  AddRef();
                                  return NOERROR;
                              }
                              *result =NULL;
                              return ResultFromScode(E_NOINTERFACE);
                          }
                          ULONG __stdcall AddRef()    
                          {
                 
                              return ++m_refCount;
                          }
                          ULONG __stdcall Release()  
                          {
                              if ( --m_refCount==0 )
                              {
                                  delete this;
                                  return 0;
                              }
                              return m_refCount;
                          }
                          HRESULT __stdcall DragEnter( IDataObject* dataObject, DWORD grfKeyState, POINTL mousePos, DWORD* effect )
                          {
                              *effect =DROPEFFECT_COPY;
                              return NOERROR;
                          }
                          HRESULT __stdcall DragOver( DWORD keyState, POINTL mousePos, DWORD* effect )
                          {
                              *effect =DROPEFFECT_COPY;
                              return NOERROR;
                          }
                          HRESULT __stdcall DragLeave()
                          {
                              return NOERROR;
                          }
                          HRESULT __stdcall Drop( IDataObject* dataObject, DWORD keyState, POINTL mousePos, DWORD* effect )
                          {
                              BOOL r =::PostMessageW( m_owner, WM_MAGIC, 0, (LPARAM)0 );
                              *effect =DROPEFFECT_COPY;
                              return NOERROR;
                          }
                    };
                 
                 
                 
                    INT WINAPI WinMain( HINSTANCE, HINSTANCE, char*, INT )
                    {
                 
                        ::OleInitialize(NULL);
                 
                        WNDCLASSEX wc;
                        ::memset( &wc, 0, sizeof(wc) );
                        wc.cbSize =sizeof(wc);
                        wc.lpfnWndProc =(WNDPROC)gWindowProc;
                        wc.cbWndExtra =4;
                        wc.hInstance =::GetModuleHandleW(0);
                        wc.lpszClassName =gWindowClassName;
                        wc.hbrBackground =(HBRUSH)::GetStockObject( WHITE_BRUSH );
                        wc.hCursor =::LoadCursorW( NULL, IDC_ARROW );
                        ::RegisterClassExW( &wc );
                 
                 
                        HWND h =::CreateWindowExW(
                            0,
                            wc.lpszClassName,
                            NULL,
                            WS_OVERLAPPEDWINDOW,
                            100, 100,
                            200, 200,
                            NULL,
                            NULL,
                            ::GetModuleHandleW(0),
                            NULL );
                 
                        ::ShowWindow( h, SW_NORMAL );
                 
                 
                        MyDropTarget dt(h);
                        HRESULT result =::RegisterDragDrop( h, &dt );
                 
                 
                        MSG m;
                        while ( ::GetMessageW( &m, NULL, 0, 0 )>0 )
                        {
                            ::TranslateMessage( &m );
                            ::DispatchMessageW( &m );
                        }
                 
                 
                        ::RevokeDragDrop( h );
                        ::DestroyWindow( h );
                        ::UnregisterClassW( gWindowClassName, ::GetModuleHandleW(0) );
                        ::OleUninitialize();
                 
                 
                        return 0;
                 
                    };
              Сообщение отредактировано: Emura -
                Мне кажется это как то связано с этим куском кода
                Ты тут намеренно усыпляешь все приложение на 5 секунд, собвствено приложение не реагирует вообще ни на что, с таким подходом приложение может подвесить и твой Drag and Drop
                ExpandedWrap disabled
                          case WM_MAGIC:
                              {
                                  for ( int i=0; i<50; ++i )
                                  {
                                      ::Sleep(100);
                                  }
                                  return 0;
                                  break;
                              }
                  Dem_max
                  sleep для примера, реально там происходит обработка файлов. тело Drop функции отрабатывается раньше чем присходит заход в блок WM_MAGIC (благодаря PostMessage), по этой причине не использовал SendMessage. думалось что explorer получает управление после Drop(), но это почему-то не так.

                  для справки, например, если использовать WM_DROPFILES и делать обработку в блоке WM_DROPFILES то все ок, explorer не виснет.

                  еще интересно если во время обработки выскакивает мессаджбокс(вызываемый алгоритмом обработки), то explorer размораживается.. :ph34r:
                  Сообщение отредактировано: Emura -
                    Цитата
                    sleep для примера

                    Я понимаю что для примера, но он то и блокирует у тебя поток.
                      посоветовали использовать таймер, но смахивает на костыль, попробую..
                        Можешь обойтись и без Ole Drag&Drop

                        Цитата Emura @
                        например есть кнопка позволяющая кидать на себя файлы, естественно делаем топ-окну WS_EX_ACCEPTFILES.
                        неприятность в том, что курсор принимает вид "можно бросить" в любом месте окна. Как сделать, чтобы курсор изменялся только находясь над кнопкой (не делая кнопку окном(HWND))?

                        Есть недокументированное сообщение

                        ExpandedWrap disabled
                          #define WM_QUERYDROPOBJECT  0x022B

                        Цитата
                        WM_QUERYDROPOBJECT
                        Значение:
                        0x22b
                        Параметры:
                        wParam 0, если курсор находится над рабочей областью окна, иначе 1.
                        lParam Указатель на структуру DRAGINFO, содержащую информацию об операции.
                        Комментарии:
                        Сообщение посылается окну, над которым находится перемещаемый объект, чтобы узнать, может ли оно принять этот объект. В случае возможности приема, оконная процедура должна после обработки возвратить TRUE.

                        Это выдержка из документации по недокументированным сообщениям Win 3.1, однако вплоть до Win XP/7 этот механизм похоже не менялся.

                        Попробуй сам его обработать, если окну с помощью DragAcceptFiles или вручную установлен стиль WS_EX_ACCEPTFILES. В обработчике, если курсор над кнопкой возвращай TRUE, иначе FALSE.

                        Если ты хочешь Ole Drag&Drop

                        Цитата
                        PostMessage с путем папки;

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

                        ExpandedWrap disabled
                           
                          for ( int i=0; i<50; ++i )
                          {
                               ::Sleep(100);
                          }


                        Это вообще зачем ?
                        Сообщение отредактировано: Jenya -
                          Jenya
                          Ole Drag&Drop, не то что хочу, без него не обойтись, не использовал бы с радостью, если бы можно было. используется по той причине что надо контролировать вид курсора в пределах одного окна(окно - место для виджетов), специфика задачи.

                          Цитата

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

                          это всё учитывается, за подсказку спасибо :)

                          Цитата
                          Это вообще зачем ?

                          это для тестового примера(код выше), как некое действие занимающее поток.

                          на данный момент попробовал с таймером - работает. оставлю его, если более никто не подскажет другого.
                          Сообщение отредактировано: Emura -
                            Всем привет! Тема давно закрыта. Но чтобы не плодить новых тем, напишу тут.
                            Я использую IDropTarget
                            Мне нужно почти то же самое, о чем писал автор, НО.
                            Если упростить, то у меня есть 2 формы - первая должна увидеть драг файла и отобразить вторую форму, которая и принимает файлы.
                            Все прекрасно работает, кроме одного нюанса: мне нужно, чтобы первая форма, которая только сигналит второй форме о том, что начался Драг, не умела принимать файл, а только сигналить о начале драга, или о уводе мышки с окна вообще и тогда снова скрывать вторую форму, или говорить о том, что скинули файл на нее и тоже просто скрывать вторую форму.
                            Я к чему - это все работает, но нужно, в момент, пока мышка с файлом бродит по первой форме, не залезая в область второй, мышка имела бы "запретительный" вид. У меня получается такое добиться только если в функции DragEnter я укажу Result = False. НО тогда вообще отключается проверка на Драг и например если скинуть файл на первую форму, то вторая форма так и останется висеть, хотя друг уже закончился...
                            Как мне менять курсор мышки, не отключая механизм Драга в первой форме?
                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                            0 пользователей:


                            Рейтинг@Mail.ru
                            [ Script execution time: 0,0380 ]   [ 16 queries used ]   [ Generated: 29.03.24, 15:54 GMT ]