On Windows, when you use the mouse to click and drag in a scrollbar to scroll it up and down, you can move the mouse approximately ~120 pixels away from the scrollbar before the dragging stops working. (By contrast, on the mac you appear to be able to move it anywhere on the screen and the drag will still happen.)
Is there a constant I can get at, maybe using SystemParametersInfo or something, to get the OS-defined value for this? I'm using a control that simulates a scrollbar, and I'd like to use the same behavior for how far you can drag away from the bar before scrolling stops.
Thanks!
GetSystemMetrics has a lot of these values. However, there is no Windows API that retrieves this value.
As an aside, you should think carefully before simulating a control. There is a lot more code to implementing the control correctly (including support for accessibility, keyboarding and other behaviours) that will tend to make your scroll bar either lacking in features or more costly than you intend.
Related
I'm using CDateTimeCtrl in my dialog application. Now we have already agreed with the client about the size of the CDateTimeCtrl. The 1st problem is, it is by default left-aligned, and is really close to the left border. The 2nd problem is it leaves a really wide space on the right side of the control. Hence, the solution to solve both problems would be to center align text.
Unfortunately, in the Properties window, there is no alignment property (except for "Right align" in which there were no changes when I tried to toggle it).
Now, I've tried calling CWnd::ModifyStyle in the OnInitDialog() event. Also, no luck with this.
For the actual code,
auto timePicker = (CDateTimeCtrl*)GetDlgItem(IDC_TIME_PICKER);
timePicker->ModifyStyle(0, SS_CENTER);
return TRUE; // this function is the OnInitDialog()
What could I be missing that calling this function does not center the text of CDateTimeCtrl?
You can't use a style that is suited for a static control and use the style in a date time control.
All available styles are listed here.
The control itself also doesn't have child controls. It draw the values itself.
Maybe there is a chance to subclass the control and overwrite the WM_PAINT message and doing a kind of ownerdrawing by yourself.
I don't use the date time picker and I confess: I don't like it at all. I wrote a complete own control that is much more flexible.
I searched, but most posts are just telling me what I already have, so below is basically my code right now:
DIKeyboard->Acquire();
DIMouse->Acquire();
DIMouse->GetDeviceState(sizeof(DIMOUSESTATE), &mouseCurrState);
DIKeyboard->GetDeviceState(sizeof(keyboardState),(LPVOID)&keyboardState);
MousePos.x += mouseCurrState.lX;
MousePos.y += mouseCurrState.lY;
Any post telling me how to get absolute position just says to use those last two lines. But my program is windowed, and the mouse can start anywhere on the screen.
i.e. If my mouse happens to be in the centre of my screen, that becomes position 0,0. I basically just want the top left of my window (not my screen) to be my 0,0 mouse coordinates, but am having a hard time finding anything relevant.
Thanks for any help! :)
Following the discussion in the comments, you'll have to decide which method works best for you. Unfortunately, having never worked with DirectInput, I do not know the ins-and-outs of it.
However, Window Messages work best for RTS-style controls, where a cursor is drawn to screen. This is due to the fact that this respects user settings, such as mouse acceleration and mouse speed, whereas DirectInput only uses the driver settings (so not the control panel settings). The user will expect the mouse to feel the same, especially in windowed mode.
DirectInput works better for FPS-style controls, when there is no cursor drawn, as window messages give you only the cursor coordinates, and not offset values. This means that once you are at the edge of the screen, window messages will no longer allow you to detect the mouse being moved further (actually, I am not 100% sure on this, so if someone could verify, please feel free to comment).
For keyboard, I would definitely suggest window messages, because DirectInput offers no advantages, and WM input is easier to use, and quite powerful (the WM_KEYDOWN messages contains a lot of useful data), and it'll allow you (via TranslateMessage) to get good text input, adjusted to locale, etc.).
Solving your problem with DirectInput:
You could probably use GetCursorPos followed by ScreenToClient to initialise your MousePos structure. I'm guessing you'll need to redo this every time you lose mouse input and reacquire it.
Hybrid solution (for RTS like controls):
It might be possible to use a hybrid solution for the mouse if you desire RTS-like controls. If this is the case, I suggest, though I have not tested this, to use WM for the movement of the mouse, which avoids the need for workaround mentioned above, and only use DirectInput to detect additional mouse buttons.
Now one thing I think you should do in such a hybrid approach is not directly use the button when you detect it via DirectInput, but rather post a custom application message to your own message queue (using PostMessage and WM_APP) with the relevant information. I suggest this because using WM you do not get the real-time state of the mouse & keyboard, but rather the state at the time of the message. Posting a message that the button was pressed allows you to handle the extra buttons in the same state-dependent manner (I don't know how noticeable this 'lag' effect is). It also makes the entire input handling very uniform, as every bit of input with this enters as a window message.
In a view of my MFC application, I can select certain rectangular area with click & drag. But when user wants to select larger area than current screen, he can't do that because the view does not automatically scroll when mouse pointer is near bound of the client area.
How can I resolve this problem? Any reference would suffice.
Normally you only do this when the user has the mouse button held down. That being the case, you normally want to capture the mouse when the click. You'll then handle WM_MOUSEMOVE messages. In your case, you'll compare the current position of the mouse to the border of your window, and when it gets close enough (e.g., within 10 pixels) you start to scroll in that position.
I feel obliged to add that I'd control scrolling speed pretty carefully when you do this -- some programs scroll so far so fast that this becomes nearly unusable, because the moment you've gotten close to the edge of the window, you've already scrolled way past where you intended. Others tend toward the opposite: no matter what you do, they scroll so slowly that moving even a short distance seems like it takes forever.
I doubt there's an easy answer to getting the "right" speed. You do generally want a gradient, so as they get sort of close to the border, it scrolls slowly, and as they get closer, the scrolling gets faster. You still need to be fairly careful about the upper and lower bounds of that though, so they get a reasonable range of speeds, not just jumping from "oh, am I ever going to get there", directly to "whoa, back up, that's way too far already!".
I'm currently using Google Chrome as my main browser. I wondered how the developers put the custom titlebar, because I wanted to incorporate into one of my own applications.
If you guys don't know what I'm talking about, here's a picture:
I found an article about the interface, which is here:http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/33870516-9868-48d3-ab53-6269d9979598
However, I don't know how to do this. I'm currently using VC++ Express. Can anyone give me step by step instructions and how to get an interface like that? Except I don't want tabs on top.
I'm writing this in Win32.
If memory serves, the main things you need to handle aren't WM_NCCALCSIZE, but WM_NCHITTEST and WM_NCPAINT.
WM_NCHITTEST is what tells the system when the cursor is over the title bar, so you need to take a cursor position and decide whether it's over the area you consider "title bar". In particular, if the user clicks and drags with the cursor in this area, the whole window gets dragged.
WM_NCPAINT is just like WM_PAINT except for the non-client area -- i.e., this is when you need to actually draw whatever you're going to for the title bar (and window borders, if memory serves).
I should add that I haven't played with this in quite a while. There's almost certainly more I'm not remembering right now.
OK, the answer is simple:
Chomre simply does not use the Windows built in functionality for drawing a frame border, titlebar, titlebar buttons, etc..
When you call GetWindowRect(hChromeWindow) and GetClientRect(hChromeWindow) you will notice that the rectangles are identical. This means that Chrome turns off all Windows functionality for drawing a border (simply return 0 in WM_NCCALSIZE without doing anything else) and then they draw EVERYTHING into the client area.
So in WM_PAINT they draw the titlebar and the upper part of the window (URL bar, tabs, etc..) together. In WM_NCPAINT they do nothing.
This is not the common way to do it, but the easiest, and it is bullet-proof.
By the way: Java applications do the same.
I am building a custom win32 control/widget and would like to change the cursor to a horizontal "splitter" symbol when hovering over a particular vertical line in the control. IE: I want to drag this vertical line (splitter bar) left and right (WEST and EAST).
Of the the system cursors (OCR_*), the only cursor that makes sense is the OCR_SIZEWE. Unfortunately, that is the big, awkward cursor the system uses when resizing a window. Instead, I am looking for the cursor that is about 20 pixels tall and around 3 or 4 pixel wide with two small arrows pointing left and right.
I can easily draw this and include it as a resource in my application but the cursor itself is so prevalent that I wanted to be sure it wasn't missing something.
For example: when you use the COM drag and drop mechanism (CLSID_DragDropHelper, IDropTarget, etc) you implicitly have access to the "drag" icon (little box under the pointer). I didn't see an explicit OCR_* constant for this guy ... so likewise, if I can't find this splitter cursor outright, I am wondering if it is part of a COM object or something else in the win32 lib.
There are all sorts of icons, cursors, and images in use throughout the Windows UI which are not publicly available to 3rd-party software. Of course, you could still load up the module in which they reside and use them, but there's really no guarantee your program will keep working after a system update / upgrade.
Include your own. The last thing you want is adding an extra dependency over a tiny little cursor.
I had this exact problem. When I looked back over some old code for a vertical splitter thinking I had an easy answer, it turned out that I had build and loaded my own resource:
SetCursor( LoadCursor( ghInstance, "IDC_SPLITVERT" ));
I vaguely remember investing some considerable time and effort into find the system way of doing it, so (my guess) is that there is not a system ICON readily available to do the job, so you are better off rolling your own.
This is one of those times when I would like to be wrong, as I would have liked there to be a system icon for this job.