How to handle double click exactly? - winapi

I want to handle action double click by clicking left_mouse 2 times.Between 2 click-time,I sleep 100ms
SendInput(LEFT_CLICK...); Sleep(100); SendInput(LEFT_CLICK...);
It works OK in my PC,but not works correctly in virtual machine
May be,There is a delay-time when machine do function "SendInput"Eventhough I remove "Sleep(100)",It just clicks 2 times and doesn't "double click" as I want.
How to handle double click exactly in this case
Please suggest me anyway to do it
Thanks,

Btw you should specify what environment you're working in and make your code a bit more detailed. Using SendInput is one option, I don't know what you're trying to do exactly, but I'll give you two more options to try for simulating clicks. Something like this would works fine (I code in python but it should be the same idea):
def leftClick(x=0, y=0):
win32api.SetCursorPos((x,y)) #set the cursor to where you wanna click
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x, y, 0, 0) #generate a mouse event
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x, y, 0, 0)
return True
def doubleClick(x=0, y=0):
leftClick(x,y)
leftClick(x,y)
You could sleep for 50 ms in between time.sleep(0.05) but it works for me without it and I've tested in a vm.
Another option if you want to perform silent clicks without having to move the cursor, you can send a message to the window where you want to click knowing the window handle (hwnd), here I assume you pass the handle as a parameter.
def leftClick(x=0, y=0, hwnd):
lParam = win32api.MAKELONG(x,y) # create a c long type to hold your click coordinates
win32gui.SendMessage(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, lparam) # send a message to the window that the mouse left button is down.
win32gui.SendMessage(hwnd, win32con.WM_LBUTTONUP, 0, lparam) # send a message to the window that the mouse left button is up.
return True
def doubleClick(x=0, y=0, hwnd):
leftClick(x,y, hwnd)
leftClick(x,y, hwnd)
or you can send the message WM_LBUTTONDBLCLK up to you.

Related

Any suggestions to effectively update the status bar of an application?

The status bar window of this program needs to be updated every time the user press a key that is likely to move the caret of the EDIT control, and the code below works like a charm! In a nutshell, pressing a key on the keyboard will update some values and send a message "ECM_GETLINEINFOS" that is next processed in the main window procedure (code below)
However, there is flickering that is not disturbing, of course, but I wonder if it's related to how I set the text on the status bar (maybe too many updates ?) or just a problem with the drawing part.
PS: The flickering occurs on the text, not the status bar in itself, so that is why I'm questioning how I should manage the update of my window.
constexpr int failed_val = -1;
LRESULT MainWindow::HandleMessage(UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
// Custom message sent by an EDIT control, I
// use this message to tell the status bar it must update its text.
case CEM_GETLINEINFO:
{
const size_t buffSz = 24;
std::wstring buffer(buffSz, L'\0');
int line = LOWORD(wParam);
int column = HIWORD(wParam);
int count = _snwprintf_s(buffer.data(), buffer.size(),
_TRUNCATE, L"Ln %d, Col %d", line, column);
if (count != failed_val) {
// Param 1 : The text to be displayed
// Param 2 : Which status bar part
m_statusBar->SetText(buffer, 0);
}
}
return 0;
}
}
Just as Flicker-Free Displays Using an Off-Screen DC directed by the answer said,
What makes this window flicker when we update it frequently? The
answer is that Windows asks the window procedure to repaint the window
as a two-step process. First, it sends a WM_ERASEBKGND message and
then a WM_PAINT message. The default handling for the WM_ERASEBKGND
message is to fill the area with the current window background color.
So the sequence of events is first to fill the area with solid color
and then to draw the text on top. The net result of doing this
frequently is that the window state alternates between its erased
state and its drawn stateā€”it flickers.
And
To prevent the control from flickering when we update it frequently,
we need to make two changes to how the control handles messages.
First, we need to prevent Windows from providing the default handling
of WM_ERASEBKGND messages. Secondly, we need to handle WM_PAINT
messages so that the background is painted with the window background
color and so that the changes to the control's client area happen at
once.
A status bar flicker free solution in .NET: Searching Visual Studio .NET style status bar. Or Simple Mode Status Bars could be enough.

Disable cursor changing to SizeWE for some items in Win32 header

I need to prevent resizing of some items in a Win32 header control. No problem to process the HDN_BEGINTRACK notification message and cancel it - the problem is in the cursor indicating that the item can be resized. For instance, if the first item can't be resized, I see this:
, but I'd prefer to see this:
I can ignore the cursor change by suppressing the WM_SETCURSOR message, but the problem is how to know the header item WM_SETCURSOR is generated for. I can detect the item under the mouse pointer in WM_MOUSEMOVE using the HDM_HITTEST message, but WM_MOUSEMOVE is sent to window procedure only after WM_SETCURSOR. I analyzed all notification messages for the Win32 header control, and it seems, it does not have an equivalent of the MouseEnter event that is sent to the window procedure before WM_SETCURSOR.
Any ideas how to solve this problem?
You need to sub-class the header control if you haven't already.
In the sub-class, intercept the WM_SETCURSOR message, and use GetMessagePos() to get the coordinates of the mouse. These are in screen coordinates, so you need to convert them to client coordinates for the header control hit test.
// in the window sub-class
if (uMsg == WM_SETCURSOR)
{
DWORD dwPos = GetMessagePos();
HDHITTESTINFO hti;
hti.pt.x = GET_X_LPARAM(dwPos);
hti.pt.y = GET_Y_LPARAM(dwPos);
ScreenToClient(hWnd, &hti.pt);
SendMessage(hWnd, HDM_HITTEST, 0, reinterpret_cast<LPARAM>(&hti));
if (...) // test for items we want to block
{
SetCursor(LoadCursor(0, IDC_ARROW));
return TRUE;
}
// pass through to regular WndProc
}

Double click in empty area of CListBox does not call my double click function

I am using Visual Studio MFC for GUI programming.
I currently have a CListBox, and I want it to call a function when I double click on an empty part of it. (when no item is selected) Currently, I am only able to add items to it by pressing a separate button.
I made the following test code to test whether the CListBox is responding to a double click at an empty spot.
BEGIN_MESSAGE_MAP(CScnBuildDlg, CDialog)
ON_LBN_DBLCLK(IDC_EVENT_LIST, OnDblclkEventList)
END_MESSAGE_MAP()
void CScnBuildDlg::OnDblclkEventList()
{
exit(-1); //Currently, it only exits when double clicking on a specific item, not on an empty space
}
Any ideas on how to fix this?
Thanks.
An additional way of trapping this event is possible by using CWnd::Oncommand. If you add this event handler to your dialog code as follows, you will be able to trap the double-click.
BOOL CScnBuildDlg::OnCommand(
WPARAM wParam,
LPARAM lParam
)
{
if (LOWORD(wParam) == IDC_EVENT_LIST && HIWORD(wParam) == LBN_DBLCLK)
DoSomething ();
return CDialog::OnCommand(wParam, lParam);
}
However, you'll need to be careful because this event will trap the double-click on an existing list box item as well. You'll also need to make sure that you allow the base class a chance to handle the WM_COMMAND message. If not, you may experience some strange bugs.

Showing a windows with XCB / Strange Behaviour

I'm trying to show a window in xcb, inside the main window, but actually without luck.
The idea is that when the user press a button (in that case the X button) a small white window is shown (just for test).
But actually i'm stuck on that step. I watched the example code here:
http://en.wikibooks.org/wiki/X_Window_Programming/XCB
And tried to do the same in my application.
[EDIT 28/10/2013] Now with that code i can show a window, but if i try to add other variable like int i=0, or whatever, the window doesn't appear, and no expose events were raised (all events that were raised are or 0 or 2 (even if i add the variables inside other events). Any idea?
This is the XCB_KEY_PRESS event handler code:
Edit (with the new code)
case XCB_KEY_PRESS:{
xcb_key_press_event_t *kp = (xcb_key_press_event_t *)ev;
if(kp->detail==53){
printf("X pressed\n");
uint32_t vals[2];
mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
vals[0]=screen->white_pixel;
vals[1]=XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS;
win = xcb_generate_id(connection);
xcb_create_window(
connection,
XCB_COPY_FROM_PARENT,
win,
root,
80,80,
150,150,
10,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
mask, values);
mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
vals[0]=screen->white_pixel;
vals[1]=0;
background=xcb_generate_id(connection);
xcb_create_gc(connection, background, win, mask, vals);
xcb_map_window(connection,win);
xcb_flush(connection);
printf("finished\n");
}
printf("KEY_PRESS - Pressed: %d\n", kp->detail);
}
root is the root window obtained from xcb_screen_t variable.
The definition of background and win are the following:
xcb_window_t win;
xcb_gcontext_t background;
And i added even a XCB_EXPOSE event handler:
case XCB_EXPOSE:{
printf("EXPOSE NEW WINDOW CREATED\n");
xcb_poly_fill_rectangle(connection, win, background,1,&rectangle);
xcb_flush(connection);
}
What is wrong with that code? What am i missing? (I'm trying to develop a very basic window manager, just for fun)
(My idea for that program is that when x is pressed an input box is shown, do you have any suggestion on how to do that?)

Programmatically change keyboard-layout [duplicate]

I found this keyboard hook code, which I'm trying to slightly modify for my purposes: http://blogs.msdn.com/toub/archive/2006/05/03/589423.aspx
As an overview, I want to have the user press a key, say 'E', and have the keyboard return a different character, 'Z', to whatever app is in focus.
The relevant method I changed now looks like:
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
//The truely typed character:
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine((Keys)vkCode);
KBDLLHOOKSTRUCT replacementKey = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
replacementKey.vkCode = 90; // char 'Z'
Marshal.StructureToPtr(replacementKey, lParam, false);
//Now changed to my set character
vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine((Keys)vkCode);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
The console correctly outputs this as:
E
Z
T
Z
G
Z
etc.
HOWEVER, the in focus app still types 'E' instead of 'Z'. Why? I changed the hooked keyboard input to contain 'Z' instead of 'E', and the console lines show that it was changed correctly!
As I understand it, calling the return CallNextHookEx(_hookID, nCode, wParam, lParam); is what sends the "print this now" command to the open app. Is that not how it works? Is there something that's preventing me from typing the character I want? I know apps like AutoHotkey take an input key, check it, and return a different character. How do I do the same here?
Thanks!
I've done this before but a little different.
Instead of trying to change the parameters sent to CallNextHookEx, I 'swallowed' the key press (you can do this by returning a nonzero value from the hook procedure to prevent subsequent procedures from being called).
Then I used SendInput to send the new key that I wanted to 'inject'.
So basically it works like this:
Hook procedure identifies a target key is pressed
Call to SendInput, with the new key
Return 1 from the hook procedure to ignore the original key
Be careful of cyclic redirects, i.e. 'a' redirected to 'b' redirected to 'a', it can easily blow up ;)
You have, most likely, installed the hook "thread wide" and not "system wide", which means that the key translation will occur only for the thread installing the hook.
In order to install it "system wide" you will need two pieces: one dll having the "hook provider" and an exe managing it.
Here is a good tutorial
http://www.codeproject.com/KB/system/hooksys.aspx
and here an example:
http://www.codeguru.com/cpp/com-tech/shell/article.php/c4509/
But:
1. Installing system wide hooks can seriously screw up you system (make sure that you forward the keys that you don't translate).
2. Please... don't create another keylogger

Resources