LINUX.ORG.RU

Хоткеи в Win для GTK приложения


0

1

Написан эмулятор велокомпьютера, на С +GTK, но оказалось, что надо чтобы работало и под виндами, для этого использовалась оболочка Code Blocks. Программа должна часто получать нажатия любой кнопки мышки, но когда она не в фокусе (хоть и на первом плане всегда) клики уже не ловит. В общем, нужно перехватывать клики даже вне рабочего окна GTK, т.е. глобально. Даже, может подошло бы перехватить не клик, а хоткей клавиатуры, хотя это хуже. В самом GTK ничего для этого не нашел, пока вижу вариант через использование RegisterHotKey, но как нормально принять сигнал от нажатого хоткея? Если использую пример из мсдн http://msdn.microsoft.com/en-us/library/windows/desktop/ms646309%28v=vs.85%29.aspx

    MSG msg = {0};
    while (GetMessage(&msg, NULL, 0, 0) != 0)
    {
        if (msg.message == WM_HOTKEY)
        {
            printf("WM_HOTKEY received\n");
        }
    }
вот этот кусок вызывает вечный цикл с 99% загрузкой цпу, но хоткей, правда перехватывается. Очень плохо знаком с winAPI, как там это работает непонятно, у них это не создает цикла, очевидно. Даже не знаю куда рыть, может с этим RegisterHotKey вообще тупиковое направление?


TranslateMessage(&msg); DispatchMessage(&msg);

note173 ★★★★★
()

Если нужно перехватывать клики глобально — смотри в сторону raw input.

Deleted
()

Гугли про хуки, юный натуралист =)))

anonymous
()
Ответ на: комментарий от cattail

Ещё стоит вызывать Sleep периодически, чтобы не загружать проц сильно.

Какой нахрен Sleep в оконной процедуре?

P.S. Глибовый ивентлуп в винде работает через MsgWaitForMultipleObjects

anonymous
()
Ответ на: комментарий от k_andy

Спасибо за ответы, действительно не заметил. Я бы хотел предпочесть вариант gdk_pointer_grab, как наиболее понятный и удобный для меня, но он что-то не получается. Вот уже упростил до предела:

#include <gtk/gtk.h>
#include <gdk/gdk.h>

void click_counter (GtkWidget *widget, gpointer data)
{
	g_print("CLICK\n");
}

int main (int argc, char *argv[])
{
        GtkWidget *window;
	GtkWidget *button;
	GdkWindow * gwin;
	
        gtk_init (&argc, &argv);

        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	gtk_container_set_border_width (GTK_CONTAINER (window), 50);
	g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);

        button = gtk_button_new_with_label ("Hello World");
	gtk_container_add (GTK_CONTAINER (window), button);
	g_signal_connect (G_OBJECT (button), "button_press_event", G_CALLBACK (click_counter), NULL);
	gtk_widget_show_all (window);

	gwin = gtk_widget_get_window (button);

        gdk_pointer_grab (gwin, TRUE, GDK_ALL_EVENTS_MASK, NULL, NULL, GDK_CURRENT_TIME) ;

        gtk_main ();
        return 0;
}
Что здесь не так? Под винду это молча не работает, на линуксе вылетает с сообщением: The program 'btc' received an X Window System error. This probably reflects a bug in the program. The error was 'BadValue (integer parameter out of range for operation)'.

mm35
() автор топика
Ответ на: комментарий от Amp

Да, долго я с gdk_pointer_grab парился, пипец... в итоге под вин так ничего и не вышло, ловит события только когда мышь проходит над своим окном. Возможно, не полная поддержка под виндами в gdk-win32-2.0.lib? Очень жаль. А на линуксе, кажется gdk_pointer_grab вообще уже нет, устарел. Но мне сейчас нужно решение для вин. Следущее, что я попробовал - родную виндовс функцию хука SetWindowsHookEx, смысл которой полностью подходил моей задаче, но в результате она работает как-то странно, вот мой код:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

static HHOOK hk;

LRESULT  CALLBACK filtr_hook(int nCode, WPARAM wParam, LPARAM lParam)
{
        static int n;//просто индикатор активности 
        n++;
	printf ("%d\n",n);

	if (wParam==WM_RBUTTONDOWN)
    {
        printf("RIGHT BUTTON\n");
    }
	return CallNextHookEx(hk, nCode, wParam, lParam);
}

void win32_hook()
{
//hk = SetWindowsHookEx (WH_MOUSE, &filtr_hook, NULL, 0);
hk = SetWindowsHookEx (WH_MOUSE, &filtr_hook, GetModuleHandle(NULL), 0);
	if(!hk) printf ("ERROR hook create \n");
}

void win32_stop_hook()
{
	UnhookWindowsHookEx(hk);
}
Как есть код работает, но только когда курсор над окном терминала или самой программы, и нестабильно, секунд примерно 5-10, потом фунциклирует все кроме хука. Закомментированный вариант(глобальный) выдает 0 и не работает, об этом я читал, что так может быть, но что с этим делать? Мне надо ловить сигналы над любым окном. Если вместо 0 ставить GetCurrentThreadId() хук работает стабильно, но только над окном самой проги... Здесь решение наверняка есть, подскажите, что неправильно?

mm35
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.