I'm trying to implement a feature that changes the color of a child window when the user hovers over it. To do this, I need to receive EnterNotify events for specific child windows. I'm getting the EnterNotify events with no problem, but I can't figure out how to distinguish between which child window the EnterNotify event is coming from. How do I get the event window from an event?
if (event.type == EnterNotify && event.xcrossing.window == w11) {
std::cout << "ENTER WINDOW" << std::endl;
}
This is what I have tried with w11 being the child window. Nothing is sent to output when the EnterNotify events come in, but if I change the event.xcrossing.window equivalency to win (the parent window), as shown below, it will produce output as the EnterNotify events roll in. Thanks.
if (event.type == EnterNotify && event.xcrossing.window == win) {
std::cout << "ENTER WINDOW" << std::endl;
}
It turns out that when you create a child window using XCreateSimpleWindow, the parent window's mask input is not carried over to the child window. All I had to do was update each child window to receive EnterWindowMask events.
Related
How do I track move event for all the windows?
Like if user moves window "Pluma" my daemon would receive window name and new coordinates.
if(XCheckMaskEvent(display, -1, &event))
{
if(event.type == ConfigureNotify)
{
moved += event.xmotion.x + event.xmotion.y;
//qDebug << moved;
}
}
I tried tracking it like this, but it does not work...
You need t select SubstructureNotify mask on the root window first:
XSelectInput(display, XDefaultRootWindow(display), SubstructureNotifyMask );
This way you are telling X server "I'm interested in root window childrens move/resize/delete/create events"
This is my code:-
DWORD WINAPI ThreadMouse(void* data){
while (1){
//Check the mouse left button is pressed or not
if ((GetKeyState(VK_LBUTTON) & 0x8000) != 0)
{
MessageBox(NULL, L"Left Clicked", L"", NULL);
break;
}
//Check the mouse right button is pressed or not
if ((GetKeyState(VK_RBUTTON) & 0x100) != 0)
{
MessageBox(NULL, L"Right Clicked", L"", NULL);
break;
}
}
return 0;
}
I am getting the message multiple times instead of once
This looks like a thread, which polls the state of the mouse.
Not something that gets mouse events.
Windows can receive events.
I have a project with :-
class CImageDisplay :
public wxScrolledWindow,
public IToolTarget
{
/// omitted
void OnMouseDClick( wxMouseEvent& mouseEvent );
void OnMouseUp( wxMouseEvent& mouseEvent );
};
Where wxScrolledWindow is derived from wxWindow.
That declares functions for the mouse events.
In the cpp file, I have...
BEGIN_EVENT_TABLE(CImageDisplay, wxScrolledWindow)
EVT_MOTION(CImageDisplay::OnMouseMove )
EVT_LEFT_DOWN(CImageDisplay::OnMouseDown )
EVT_LEFT_DCLICK(CImageDisplay::OnMouseDClick )
EVT_LEFT_UP(CImageDisplay::OnMouseUp )
// omitted
END_EVENT_TABLE()
This tells wx to call my functions when the events (EVT_* occurs).
Then I can track the mouse events as they happen, but otherwise my code is not doing anything.
Check out the wx documentation (e.g. wx documentation mouse events for what events are available, and what limitations they have.
Check out the samples - e.g. plot.cpp which uses mouse events.
Your thread does not have a GUI for the user to interact with, so its key state is never updated. Each thread has its own key state, which is updated during UI message processing.
If you want to monitor the mouse in a thread without a GUI, you have two choices:
use SetWindowsHookEx() to hook the mouse using a WH_MOUSE or WH_MOUSE_LL hook. The thread will need a message loop to service the hook.
Have your thread create a hidden window (and message loop) and then use RegisterRawInputDevices() to have the mouse send WM_INPUT messages to your window.
I am having a propertysheet and it has three pages (page1, page2, page3) respectively.For which I added as messagebox whenever Cancel button is pressed or [X] is clicked or Esc is pressed.
Steps followed:
1.Ran the application.
Pressed Cancel button and message box is popped up. (Did not cancel the messagebox).
Now go to the taskbar and right click on the application icon and click "close window". Exactly here the problem arose; i.e, one more message box window is popped up.
Actually this should not happen, right? It should be restricted to only one message box.
//This is being triggered when close window or cancel button is pressed.
BOOL OnQueryCancel()
{
if(IDOK == ::MessageBox(m_hWnd, L"Closing the application",
L"Warning", MB_OKCANCEL | MB_ICONWARNING))
{
return TRUE;
}
return FALSE;
}
How can I prevent from not displaying multiple messagebox's? I should show focus to the already opened messagebox.
First, you should use AfxMessageBox, which makes it easier in MFC. Second, this is normal operation in Windows -- it's just responding to the close messages. I would add a variable to indicate the box is displayed already:
//Part of your class
BOOL m_bIsPromptActive;
BOOL OnQueryCancel()
{
if( !m_bIsPromptActive)
{
m_bIsPromptActive = TRUE;
if(IDOK == ::MessageBox(m_hWnd, L"Closing the application",
L"Warning", MB_OKCANCEL | MB_ICONWARNING))
{
return TRUE;
}
m_bIsPromptActive = FALSE;
}
else
{
// Message is already displayed. Set the focus to this window
::SetFocus( m_hWnd ); // or this->SetFocus();
// You can also look at ::BringWindowToFront()
}
return FALSE;
}
I have a qt application, window with several child widgets that are Qt::Tool windows.
When I minimize window and then restore on windows 7 child widgets appear immediately, but parent window not because of animation.
Is there any way to prevent this behavior and make child windows appear after main window?
Why don't you hide the tool windows while the main window is restoring? You can use this piece of code and adapt it to your needs:
void MainWindow::changeEvent( QEvent* e )
{
if ( e->type() == QEvent::WindowStateChange )
{
QWindowStateChangeEvent* event =
static_cast< QWindowStateChangeEvent* >( e );
if ( event->oldState() & Qt::WindowMinimized ) {
qDebug() << "The Window has been restored!";
}
else if ( (event->oldState() == Qt::WindowNoState) &&
(this->windowState() == Qt::WindowMaximized) ) {
qDebug() << "the window has been Maximized!";
}
}
}
For example, you can start a timer for a certain amount of time, and have the slot connected to your child tool windows, making them appear as you wish.
You can also play with transparency in the child tool windows, and emulate the main window effects.
As I recall, something like this will do:
setStyleSheet("background:transparent;");
setAttribute(Qt::WA_TranslucentBackground);
setWindowFlags(Qt::FramelessWindowHint);
Hope that helped!
At first my code set up the SDL environment, and proceeded to update the OpenGL context, without performing any SDL_Event processing whatsoever. This causes the window, as long as it was open, to appear to Windows to be unresponsive. The window flickers a bit. The titlebar would get "(Not Responding)" appended to it, and upon clicking inside the window it becomes grayed out, as Windows does this by default on non responsive windows. However in this state (even as and after it becomes grayed out), the OpenGL display continues to update and animate, and here's the kicker, it even does so while the window is being dragged. Clearly in this case the application isn't handling events from windows correctly, causing windows to think that it is in a hanged state. But there is clear evidence that the opengl continues to render.
Now I make one single modification to the code, which is these three lines placed in an appropriate spot inside the loop (which also does the OpenGL draw):
SDL_Event event;
if (SDL_PollEvent(&event) && event.type == SDL_QUIT)
break;
All this is doing is flushing the message queue using SDL.
Now the behavior is that Windows no longer thinks it is "Not Responding" and it does not get grayed out. No flicker. Everything seems to run swimmingly. But once I click and drag the title bar to drag the window, rendering gets blocked. I haven't debugged it to be sure, but I suspect that SDL_PollEvent blocks for the duration of the window drag.
Is there a way around this? This is interesting because part of the behavior exhibited by failing to handle events is proof that what I want is possible in theory.
Update: I found this thread: http://www.gamedev.net/topic/488074-win32-message-pump-and-opengl---rendering-pauses-while-draggingresizing/
The verdict seems to be that it comes down to certain choices that Microsoft made for us... It basically gets stuck in DefWindowProc() till the mouse is released. It would get very messy to hack a fix for this and I might be able to do a work around by rendering in another thread. But I don't even want to begin to think about juggling an OpenGL context from multiple threads, if that's even something that's possible.
Some workaround that works for me - add event filter for SDL_WINDOWEVENT_SIZE_CHANGED event and do additional SetViewport and draw frame.
int SDLApp::eventFilter(void* pthis, const SDL_Event *event)
{
if (event->type == SDL_WINDOWEVENT &&
event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
SDLApp* app = (SDLApp*)pthis;
// Note: NULL rectangle is the entire window
SDL_RenderSetViewport(app->renderer_, NULL);
app->DrawFrame();
}
return 1;
}
...
SDL_SetEventFilter((SDL_EventFilter)SDLApp::eventFilter, this);
This question is old, but the solution I'm using doesn't seem to be mentioned anywhere else, so here it is.
I got my inspiration from this answer, and it doesn't use additional threads.
#include <SDL.h>
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#include <SDL_syswm.h>
#define SIZE_MOVE_TIMER_ID 1
bool sizeMoveTimerRunning = false;
int eventWatch(void*, SDL_Event* event) {
if (event->type == SDL_SYSWMEVENT) {
const auto& winMessage = event->syswm.msg->msg.win;
if (winMessage.msg == WM_ENTERSIZEMOVE) {
// the user started dragging, so create the timer (with the minimum timeout)
// if you have vsync enabled, then this shouldn't render unnecessarily
sizeMoveTimerRunning = SetTimer(GetActiveWindow(), SIZE_MOVE_TIMER_ID, USER_TIMER_MINIMUM, nullptr);
}
else if (winMessage.msg == WM_TIMER) {
if (winMessage.wParam == SIZE_MOVE_TIMER_ID) {
// call your render function
render();
}
}
}
return 0;
}
// rendering function
void render() {
/* do your rendering here */
}
// event loop - call this function after setting up your window to start the event loop
void eventLoop() {
SDL_AddEventWatch(eventWatch, nullptr); // register the event watch function
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); // we need the native Windows events, so we can listen to WM_ENTERSIZEMOVE and WM_TIMER
while (true) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (sizeMoveTimerRunning) {
// modal drag/size loop ended, so kill the timer
KillTimer(GetActiveWindow(), SIZE_MOVE_TIMER_ID);
sizeMoveTimerRunning = false;
}
/* handle the events here */
}
render();
}
}
Of course, if your rendering function needs to keep additional state (e.g. if you're using OOP), use the void* parameter of eventWatch(void*, SDL_Event*) to pass the state.
I had a similar problem in which it would freeze video playback when the window was dragged or resized. The solution I found was to spawn a separate thread for rendering and use the main thread for input.
Example:
DWORD RenderThread(SDL_Window* window)
{
//Rendering stuff here...
}
int main()
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* window = SDL_CreateWindow("Title Here",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, h, w, SDL_WINDOW_RESIZABLE);
HANDLE hRenderThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RenderThread, window, 0, NULL);
SDL_Event event;
while (1)
{
SDL_PollEvent(&event);
switch (event.type)
{
//Event handling here...
}
}
}
Keep in mind that you MUST create the window in the thread that does event handling. If not it won't work. You can create the window in your event handling thread then pass that window pointer to your rendering thread.
I propose you created 2 threads:
Thread 1: loops calling SDL_PollEvent() (without rendering anything)
Thread 2: does OpenGL rendering (without calling SDL_PollEvent())
This way, your OpenGL context would be manipulated from a single thread. The whole solution has a minimum impact the architecture of your application.
Many windows procedures run a separate message loop until a certain event occurs, so you shouldn't rely on your main loop to do the drawing. If possible, application logic and rendering should always be handled in a separate thread.
Your main thread (that only handles message processing) doesn't need GL context at all, so you wouldn't need to worry about sharing.