I have directx embedded into a child window of my application and would like to hide the windows cursor only when it's over that client area. I know how to hide the cursor in general and did manage to find a make-shift example if only showing the cursor while it's not over any client areas, but it wasn't helpful for this.
How can I hide the cursor only while it's over a specific client area (/child window)?
edit:
this is as close as I've gotten but the cursor flickers unpredictably (as the mouse moves) while over the dx area
case WM_SETCURSOR:
{
static bool bCursorVisible = TRUE;
if( hWnd!=hwD3DArea && !bCursorVisible )
{
ShowCursor((bCursorVisible=TRUE));
}
else if( hWnd==hwD3DArea && bCursorVisible )
{
ShowCursor((bCursorVisible=FALSE));
return TRUE;
}
}
break;
edit2:
AHAH!
you have to use wParam instead of hWnd in this message
Here's the working code:
case WM_SETCURSOR:
{
static bool bCursorVisible = TRUE;
if( ((HWND)wParam)!=hwD3DArea && !bCursorVisible )
{
ShowCursor((bCursorVisible=TRUE));
}
else if( ((HWND)wParam)==hwD3DArea && bCursorVisible )
{
ShowCursor((bCursorVisible=FALSE));
return TRUE;
}
}
break;
case WM_SETCURSOR:
{
if (LOWORD(lParam) == HTCLIENT)
{
SetCursor(NULL);
return TRUE;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
I think it would be simpler if you just set the cursor for that specific client window to a null cursor.
the fix:
case WM_SETCURSOR:
{
static bool bCursorVisible = TRUE;
if( ((HWND)wParam)!=hwD3DArea && !bCursorVisible )
{
ShowCursor((bCursorVisible=TRUE));
}
else if( ((HWND)wParam)==hwD3DArea && bCursorVisible )
{
ShowCursor((bCursorVisible=FALSE));
return TRUE;
}
}
break;
I was on the right track but was using hWnd when I should have been using wParam (which holds the REAL handle of the window the cursor is in)
Related
In a standard C++/MFC MDI doc/view project, I want to implement a tracking tooltip in the view (the tabbed view windows which generally occupy most of the main frame window). So, in class MyAppView, I have a member CToolTipCtrl tooltip. Function MyAppView::OnInitialUpdate() contains the initialization
BOOL ok0 = tooltip.Create(this, TTS_ALWAYSTIP);
CRect clientRect; GetClientRect(&clientRect);
BOOL ok2 = tooltip.AddTool(this, LPSTR_TEXTCALLBACK, &clientRect, 1234/*tool ID*/);
tooltip.Activate(TRUE);
to make the entire client area of the view be the "tool". The message map contains an entry
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnNeedToolTipText)
and the function OnNeedToolTipText is defined as
BOOL MyAppView::OnNeedToolTipText(UINT id, NMHDR *pNMHDR, LRESULT *pResult)
{
UNREFERENCED_PARAMETER(id);
NMTTDISPINFO *pTTT = (NMTTDISPINFO *)pNMHDR;
UINT_PTR nID = pNMHDR->idFrom;
BOOL bRet = FALSE;
if(nID == 1234)
{
// Come here when text is needed for tracking tooltip
}
if(pTTT->uFlags & TTF_IDISHWND)
{
// idFrom is actually the HWND of the tool
nID = ::GetDlgCtrlID((HWND)nID);
if(nID)
{
_stprintf_s(pTTT->szText, sizeof(pTTT->szText) / sizeof(TCHAR),
_T("Control ID = %d"), nID);
pTTT->hinst = AfxGetResourceHandle();
bRet = TRUE;
}
}
*pResult = 0;
return bRet;
}
What happens is that only placing the mouse on the menu items (File, Edit, View, Window, Help) causes the code to enter OnNeedToolTipText, with an ID of 0-5. Moving the mouse into the client area (the view) does nothing.
How can I get the tooltip to appear in the client area of the view only?
Visual Studio 2017; C++; 64-bit Windows 7
In order to solve the problem you need to do the following:
BOOL CMyAppView::PreTranslateMessage(MSG* pMsg)
{
switch (pMsg->message)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_MOUSEMOVE:
if (m_pToolTip->GetSafeHwnd () != NULL)
{
m_pToolTip->RelayEvent(pMsg);
}
break;
}
return CScrollView::PreTranslateMessage(pMsg);
}
If you want a tracking tooltip in a view, these are the steps to follow:
Create tooltip and add the tool.
void CToolTipDemoView::OnInitialUpdate()
{
// ...
m_toolTip.Create(this, TTS_ALWAYSTIP | TTS_NOANIMATE);
m_toolTip.AddTool(this, _T("Doesn't matter"));
}
Handle WM_MOUSEMOVE message. First, call _TrackMouseEvent in order to further receive WM_MOUSELEAVE and activate the tooltip. Second, update the tooltip text, and show it at mouse pointer coordinates.
void CToolTipDemoView::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_bTrackingMouseLeave)
{
TRACKMOUSEEVENT tme = { 0 };
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = m_hWnd;
::_TrackMouseEvent(&tme);
m_toolTip.Activate(TRUE);
m_bTrackingMouseLeave = TRUE;
}
if (m_pointLastMousePos != point)
{
CString strText;
strText.Format(_T("x = %d y = %d"), point.x, point.y);
m_toolTip.UpdateTipText(strText, this);
m_toolTip.Popup();
m_pointLastMousePos = point;
}
CScrollView::OnMouseMove(nFlags, point);
}
Handle WM_MOUSELEAVE and deactivate the tooltip.
void CCToolTipDemoView::OnMouseLeave()
{
m_bTrackingMouseLeave = FALSE;
// mouse pointer leaves the window so deactivate the tooltip
m_toolTip.Activate(FALSE);
CScrollView::OnMouseLeave();
}
Notes:
there is no more necessary to handle TTN_NEEDTEXT.
also, there is no more necessary to override PreTranslateMessage
So I went back to see what I could be missing. I wrote this stuff over 10 years ago. I had also overridden a CWnd member
virtual INT_PTR OnToolHitTest( CPoint point, TOOLINFO* pTI ) const;
With:
INT_PTR HERichView::OnToolHitTest( CPoint point, TOOLINFO* pTI ) const
{
pTI->hwnd = m_hWnd;
pTI->uId = point.x + ( point.y << 16 );
CRect rect;
GetClientRect( rect );
pTI->rect= rect;
pTI->lpszText= LPSTR_TEXTCALLBACK;
return pTI->uId;
}
And I checked, it won't work without this. So your:
ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTip )
Should get called if you add the above. And only EnableToolTips( ); Should be needed.
I have not succeeded in getting the tracking tooltip to work within MFC. The closest I have come is
In message map: ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnNeedToolTipText)
In OnInitialUpdate: BOOL ok1 = EnableTrackingToolTips(TRUE);
In override of virtual function OnToolHitTest:
pTI->hwnd = m_hWnd;
pTI->uId = (UINT_PTR)m_hWnd;
pTI->uFlags = TTF_IDISHWND | TTF_ALWAYSTIP | TTF_TRACK | TTF_NOTBUTTON | TTF_ABSOLUTE | TTF_SUBCLASS;
pTI->lpszText = LPSTR_TEXTCALLBACK;
return pTI->uId;
In OnNeedToolTipText:
NMTTDISPINFO *pTTT = (NMTTDISPINFO *)pNMHDR;
UINT_PTR nID = pNMHDR->idFrom;
BOOL bRet = FALSE;
if(pTTT->uFlags & TTF_IDISHWND)
{
// idFrom is actually the HWND of the tool
nID = ::GetDlgCtrlID((HWND)nID);
if(nID)
{
CURSORINFO ci; ci.cbSize = sizeof(CURSORINFO); // get something interesting to display
GetCursorInfo(&ci);
_stprintf_s(pTTT->szText, sizeof(pTTT->szText) / sizeof(TCHAR),
_T("Control ID = %lld at (%d, %d)"), nID, ci.ptScreenPos.x, ci.ptScreenPos.y);
pTTT->hinst = AfxGetResourceHandle();
bRet = TRUE;
}
}
*pResult = 0;
return bRet;
This produces the following peculiar behavior. When I start the app and move the mouse cursor into the client area of the CScrollView, a tooltip appears right next to the cursor.
If I move the mouse carefully (smoothly) the tooltip tracks properly. After a while, though, it disappears, and no further mouse motions, including leaving the CScrollView window and returning, make it re-appear.
I think what is happening is that when the mouse cursor moves over the tooltip window, the tooltip is turned off, permanently. This disappearance does not seem to be time-related (e g, due to auto-pop); if the mouse is left untouched, the tooltip remains indefinitely.
I'm using low level hooks.
I have made this class:
class Kayz {
static int VKEY;
static void (*funcDown)();
static void (*funcUp)();
static HHOOK TheHook;
static KBDLLHOOKSTRUCT TheHookStruct;
static LRESULT _stdcall HookCallback(int, WPARAM, LPARAM);
public:
bool SetHook(int VKey, void(*FunctionDown)(), void(*FunctionUp)()) {
if (VKey < 0x07) {
if (!(TheHook = SetWindowsHookEx(WH_MOUSE_LL, &HookCallback, NULL, 0))) {
return false;
}
}
else if(VKey > 0x07){
if (!(TheHook = SetWindowsHookEx(WH_KEYBOARD_LL, &HookCallback, NULL, 0))) {
return false;
}
}
VKEY = VKey; funcDown = FunctionDown; funcUp = FunctionUp;
return true;
}
void UnSetHook() {
UnhookWindowsHookEx(TheHook);
}
};
int Kayz::VKEY;
void(*Kayz::funcDown)();
void(*Kayz::funcUp)();
HHOOK Kayz::TheHook;
KBDLLHOOKSTRUCT Kayz::TheHookStruct;
LRESULT _stdcall Kayz::HookCallback(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode >= 0) {
if (wParam == WM_KEYDOWN) {
TheHookStruct = *((KBDLLHOOKSTRUCT*)lParam);
if (TheHookStruct.vkCode == VKEY) {
(*funcDown)();
}
}
else if (wParam == WM_KEYUP)
{
TheHookStruct = *((KBDLLHOOKSTRUCT*)lParam);
if (TheHookStruct.vkCode == VKEY) {
(*funcUp)();
}
}
}
return CallNextHookEx(TheHook, nCode, wParam, lParam);
}
All the functions I put into SetHook do is change a bool variable in the main program so I can know whether or not the key is pressed. It seems to me that it's the most optimal way because I don't have to check for the key's state every time I loop in the main program.
Now.
Using a blocking timer such as Sleep() in the main program will block the program, including
return CallNextHookEx(TheHook, nCode, wParam, lParam);
That means that, as this is a low level hook, every other program is only gonna get the input when sleep ends. So if I press a key while in notepad, it's only gonna get typed when sleep ends and the program loops again, if I type a lot, they're gonna get typed most likely one at a time.
The only thing I've seen that is able to "bypass" this is
while(GetMessage(&msgVar, NULL, 0, 0)){}
GetMessage never or rarely returns, so it doesn't take up any system resources or processing power. It doesn't block because while is waiting for it to return. So basically, it's not doing anything but it isn't blocking either.
I need to have a thread that is doing something similar to this. That thread will be receiving the key press "events" and executing the functions that change the variables in the main program.
But this is dirty. I don't like dirty.
So I'd very much like to know:
How can I achieve non-blocking nothing, consuming the least possible resources, in a clean way?
Thank you.
EDIT:
As you asked: I'm making a memory aimbot strictly for learning purposes.
I have now spent quite a bit of time reading about MsgWaitForMultipleObjectsEx, and apparently you can just null the first 2 parameters, which comes in handy.
I was also thinking of doing this the wrong way, I was going to make a thread for the program to "hold" and still receive the async input from the hooks(which is why I didn't want it to block), and then the other(always-running) thread would work based on the bools that the functions the hook called would change.
I've now realized that's a rather bad design, so I'm thinking of using MsgWaitForMultipleObjectsEx in the main program, and checking that bool with it, pausing or resuming the aimbot thread if needed.
I'm now beginning to understand what #HarryJohnston said about the spaghetti logic, because I've got to organize what the async hook functions do with what the code that comes after MsgWaitForMultipleObjectsEx does, and those seem some rather difficult decisions.
I want to follow these hooks and get a full understanding of how this can all work, which is why I won't be using raw input right away, though thank you #nikau6 for informing me about it, I'll surely look into it when I'm done with hooks.
Once again thank you everyone.
"It seems to me that it's the most optimal way because I don't have to check for the key's state every time I loop in the main program."
There's a better way than hooks, not well known, to monitor the keyboard events on all the system. This is Raw Input.
With raw inputs, your application get informed of each keyboard, mouse, etc.., event, straight from the HID (Human Device Interface) driver. This is more efficient than hooks, and very simple to use. Your application don't need to export a procedure from a DLL, and because raw inputs are not hooks, no message have to be passed to an another procedure, to a another thread, after it was treated. (see one of my comments below about the DefRawInputProc procedure). The application gets the raw input through the WM_INPUT message. Unlike hooks, a window must be created, that's an obligation, a handle is asked.
Here's how I use Raw Input :
EDIT : And you'll not get the problem you have about the non-blocking thread.
#include <Windows.h>
#define HID_ISMOUSE(x) ((x).header.dwType == RIM_MOUSE)
#define HID_ISKEYBOARD(x) ((x).header.dwType == RIM_TYPEKEYBOARD)
#define HID_SCODE(x) ((x).data.keyboard.MakeCode) // scan code
#define HID_VKEY(x) ((x).data.keyboard.VKey) // virtual key code
#define HID_WMSG(x) ((x).data.keyboard.Message) // corresponding window message, WM_KEYDOWN, WM_SYSKEYDOWN, WM_KEYUP, WM_SYSKEYUP.
#define HID_ISKEYUP(x) ((x).data.keyboard.Flags & RI_KEY_BREAK)
#define HID_ISKEYDOWN(x) (((x).data.keyboard.Flags & 0x01) == RI_KEY_MAKE)
#define RAWINPUT_ERROR (UINT)-1
namespace HID
{
const USHORT MOUSE = 2;
const USHORT KEYBOARD = 6;
// Register a raw input device
bool RegisterDevice(HWND hTarget, USHORT usage)
{
RAWINPUTDEVICE hid;
hid.usUsagePage = 1; // generic desktop page
hid.usUsage = usage; // device id
hid.hwndTarget = hTarget; // window handle
hid.dwFlags = RIDEV_NOLEGACY | RIDEV_INPUTSINK ; // RIDEV_INPUTSINK to monitor all the system, RIDEV_NOLEGACY if you don't want legacy keyboard events.
return !!RegisterRawInputDevices(&hid, 1, sizeof(RAWINPUTDEVICE));
}
// Unregister a raw input device.
void UnregisterDevice(USHORT usage)
{
RAWINPUTDEVICE hid;
hid.usUsagePage = 1;
hid.usUsage = usage;
hid.dwFlags = RIDEV_REMOVE; // RIDEV_REMOVE to remove a device.
hid.hwndTarget = NULL; // NULL to remove a device.
RegisterRawInputDevices(&hid, 1, sizeof(RAWINPUTDEVICE));
}
// Get raw input data
bool GetInputData(HRAWINPUT hInput, RAWINPUT* RawInput)
{
UINT size = sizeof(RAWINPUT); // size = 40
if( GetRawInputData((HRAWINPUT)hInput, RID_INPUT, RawInput, &size, sizeof(RAWINPUTHEADER)) != RAWINPUT_ERROR )
return true;
else
return false;
}
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR cmd_line, int cmd_show)
{
WNDCLASSW wc = {0};
wc.lpfnWndProc = WindowProc;
...
HWND hwnd = ::CreateWindowW(...);
...
HID::RegisterDevice(hwnd, HID::KEYBOARD);
MSG msg;
while(GetMessageW(&msg, NULL, 0, 0))
{
DispatchMessageW(&msg);
}
HID::UnregisterDevice(HID::KEYBOARD);
return (int)msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if(msg == WM_INPUT) // Raw input message.
{
RAWINPUT Input;
if(HID::GetInputData((HRAWINPUT)lParam, &Input))
{
if(HID_ISKEYBOARD(Input))
{
if(HID_ISKEYUP(Input))
{
return 0;
}
else // if(HID_ISKEYDOWN(Input))
{
return 0;
}
}
}
}
return ::DefWindowProc(hWnd, msg, wParam, lParam);
}
you need use MsgWaitForMultipleObjectsEx in loop this is most power function for you. with this you will be wait for windows(and hooks) messages, for multiple events (up to 63) also you can receiver user mode APC calls and periodically (by timeout do same tasks). example:
void ZApp::Run()
{
for (;;)
{
HANDLE* pHandles;
DWORD nCount = GetWaitHandles(&pHandles);
DWORD r = MsgWaitForMultipleObjectsEx(nCount, pHandles, GetTimeout(), QS_ALLINPUT, MWMO_ALERTABLE);
if (r < nCount)
{
OnSignalObject(r);
continue;
}
if (r == nCount)
{
BOOL bIdle = FALSE;
MSG msg;
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (!bIdle)
{
bIdle = IsIdleMessage(msg.message);
}
if (PreTranslateMessage(&msg)) continue;
if (msg.message == WM_QUIT)
{
return ;
}
if (!IsDialogMessageEx(&msg))
{
if (msg.message - WM_KEYFIRST <= WM_KEYLAST - WM_KEYFIRST)
{
TranslateMessage(&msg);
}
DispatchMessage(&msg);
}
}
if (bIdle)
{
OnIdle();
}
continue;
}
if (r - WAIT_ABANDONED_0 < nCount)
{
OnAbandonedObject(r - WAIT_ABANDONED_0);
continue;
}
switch(r)
{
case WAIT_TIMEOUT:
OnTimeout();
break;
case WAIT_IO_COMPLETION:
OnApcAlert();
break;
default: __debugbreak();
}
}
}
I've realized that having a thread permanently "on hold" when waiting for hooks to execute other functions is just a bad way of doing what I was looking for, you should always have every thread doing something. If you're following the same path I suggest you get off of it and organize your code in a way you don't have to have these "loose ends".
Thanks everyone. Mainly #RbMm who informed me of MsgWaitForMultipleObjectsEx and guided me through it, and #nikau6 who informed about RawInput, which I'll be using in the future.
I've also finalized the class and included a function that returns when your key is either pressed or released(false when MsgWaitForMultipleObjectsEx returns anything other than WAIT_OBJECT_0), figured I'd post it here in case anyone ever needs it since most of the conversation was made in the comments and I often skip those when browsing stackoverflow.
class Kayz {
static bool KDown[2];
static int VKEY;
static void (*funcDown)();
static void (*funcUp)();
static HHOOK TheHook;
static KBDLLHOOKSTRUCT TheHookStruct;
static LRESULT _stdcall HookCallback(int, WPARAM, LPARAM);
public:
bool SetHook(int VKey, void(*FunctionDown)(), void(*FunctionUp)()) {
if (VKey < 0x07) {
if (!(TheHook = SetWindowsHookEx(WH_MOUSE_LL, &HookCallback, NULL, 0))) {
return false;
}
}
else if(VKey > 0x07){
if (!(TheHook = SetWindowsHookEx(WH_KEYBOARD_LL, &HookCallback, NULL, 0))) {
return false;
}
}
VKEY = VKey; funcDown = FunctionDown; funcUp = FunctionUp;
return true;
}
void UnSetHook() {
UnhookWindowsHookEx(TheHook);
}
bool WaitOnKey()
{
MSG msg;
while (true) {
if (MsgWaitForMultipleObjectsEx(0, 0, INFINITE, QS_ALLINPUT, 0) == WAIT_OBJECT_0) {
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
if (msg.message != WM_QUIT) return false;
TranslateMessage(&msg); DispatchMessage(&msg);
}
if(KDown[0] == 0 && KDown[1] == 0){
continue;
}else if (KDown[0] == true) {
return true;
}else{
KDown[1] = false;
return true;
}
} else {
return false;
}
}
}
};
bool Kayz::KDown[2];
int Kayz::VKEY;
void(*Kayz::funcDown)();
void(*Kayz::funcUp)();
HHOOK Kayz::TheHook;
KBDLLHOOKSTRUCT Kayz::TheHookStruct;
LRESULT _stdcall Kayz::HookCallback(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode >= 0) {
if (wParam == WM_KEYDOWN) {
TheHookStruct = *((KBDLLHOOKSTRUCT*)lParam);
if (TheHookStruct.vkCode == VKEY) {
KDown[0] = true;
(*funcDown)();
}
}
else if (wParam == WM_KEYUP)
{
TheHookStruct = *((KBDLLHOOKSTRUCT*)lParam);
if (TheHookStruct.vkCode == VKEY) {
KDown[1] = true;
KDown[0] = false;
(*funcUp)();
}
}
}
return CallNextHookEx(TheHook, nCode, wParam, lParam);
}
I want to track event of single left-click on edit control.
I override PretranslateMessage function as below:
BOOL CMyClass::PreTranslateMessage(Msg* pMsg)
{
switch(pMsg->message)
case WM_LBUTTONDOWN:
{
CWnd* pWnd = GetFocus();
if (pWnd->GetDlgCtrlID == MY_EDIT_CTRL_ID)
{
//Do some thing
}
break;
}
}
The problem is that when I click on the edit control, all other control become disabled (for example buttons don't respond to clicks etc.)
How can I fix this problem? Or how can I track click notificationN on edit box?
You need this:
BOOL CMyClass::PreTranslateMessage(MSG* pMsg)
{
switch(pMsg->message)
{
case WM_LBUTTONDOWN:
{
CWnd* pWnd = GetFocus();
if (pWnd->GetDlgCtrlID() == MY_EDIT_CTRL_ID) // << typo corrected here
{
//Do some thing
}
break;
}
}
return __super::PreTranslateMessage(pMsg); //<< added
}
BTW its a bit awkword to use a switch statement here. Following code is cleaner IMO, unless you want to add morecases than only WM_LBUTTONDOWN:
BOOL CMyClass::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_LBUTTONDOWN)
{
CWnd* pWnd = GetFocus();
if (pWnd->GetDlgCtrlID() == MY_EDIT_CTRL_ID)
{
//Do some thing
}
}
return __super::PreTranslateMessage(pMsg); //<< added
}
I'm using rawinput with directx...i'm trying to zoom with the camera when mouse wheel is used...when I run the program with the following code, the data I get from rawinput for the usbuttondata goes to 120 when I push mouse wheel forward...then it goes out of control...up to 65000...I thought the data was supposed to be 1 or -1 or 0...what does rawinput send as the mouse wheel data?
code:
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg,
WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
case WM_CREATE:
{
RAWINPUTDEVICE Rid[2];
// Keyboard
Rid[0].usUsagePage = 1;
Rid[0].usUsage = 6;
Rid[0].dwFlags = 0;
Rid[0].hwndTarget=Inst.Wnd.hWnd;
// Mouse
Rid[1].usUsagePage = 1;
Rid[1].usUsage = 2;
Rid[1].dwFlags = 0;
Rid[1].hwndTarget=Inst.Wnd.hWnd;
if (!RegisterRawInputDevices(Rid,2,sizeof(RAWINPUTDEVICE)))
{
MessageBox(NULL, L"Failed to Register Input Devices!", L"ALERT", MB_OK);
exit(1);
}
return 0;
}
case WM_INPUT:
{
// Determine how big the buffer should be
UINT iBuffer;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &iBuffer,
sizeof(RAWINPUTHEADER));
LPBYTE lpb = new BYTE[iBuffer];
if (lpb == NULL)
{
return 0;
}
UINT readSize = GetRawInputData( (HRAWINPUT)lParam, RID_INPUT, lpb, &iBuffer, sizeof(RAWINPUTHEADER) ) ;
if( readSize != iBuffer )
puts( "ERROR: GetRawInputData didn't return correct size!" ) ;
RAWINPUT *raw = (RAWINPUT*) lpb;
if (raw->header.dwType== RIM_TYPEMOUSE)
{
riProcessMouseMessage(&raw->data.mouse);
}
if (raw->header.dwType== RIM_TYPEKEYBOARD)
{
//riProcessKeyboardMessage(&raw->data.keyboard);
}
}
return 0;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDM_FILE_NEW:
{
// Create the game object
pGame = new CGame(dxMgr.getD3DDevice());
// Initialize the game object
if (!pGame->init(Inst.Wnd.hWnd))
return 0;
break;
}
case IDM_FILE_OPEN:
pGame->m_animCollection->LoadXFile("oxana.x", 0);
//objects.CreateNewObject(1, L"oxana.x", NULL);
break;
case IDM_FILE_SAVE:
break;
case IDM_FILE_SAVEAS:
break;
case IDM_FILE_EXIT:
PostQuitMessage(WM_QUIT);
break;
}
return 0;
case WM_DESTROY:
PostQuitMessage(WM_QUIT);
return 0;
default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return TRUE;
}
void riProcessMouseMessage( const RAWMOUSE* rmouse )
{
if(pGame != NULL)
{
//MessageBox(NULL, L"Game Found", L"SUCCESS", MB_OK);
if ( MOUSE_MOVE_RELATIVE == rmouse->usFlags )
{
riMgr.mxr = &rmouse->lLastX;
riMgr.myr = &rmouse->lLastY;
}
riMgr.mzr = (RI_MOUSE_WHEEL & rmouse->usButtonFlags) ? &rmouse->usButtonData : 0;
}
}
I suspect it is the same as WM_MOUSEWHEEL:
The high-order word indicates the distance the wheel is rotated, expressed in multiples or divisions of WHEEL_DELTA, which is 120. A positive value indicates that the wheel was rotated forward, away from the user; a negative value indicates that the wheel was rotated backward, toward the user.
The low-order word indicates whether various virtual keys are down.
Therefore you need to extract the high order word. You need to take care to handle negative values correctly. You probably don't as you get large values instead.
If you want you can use the following macro for this: GET_WHEEL_DELTA_WPARAM(wParam)
Add the following in the switch statment
case WM_MOUSEWHEEL:
{
int delta = GET_WHEEL_DELTA_WPARAM(wparam);
if(delta > 0)
{
//Mouse Wheel Up
}
else
{
//Mouse Wheel Down
}
return 0;
}
How can I check if an other app is running in full screen mode & topmost in c++ MFC?
I just want to disable all of my auto dialogs (warnings) if media player or other players are running. (Like silent/gamer mode in Avast.)
How could I do that?
Thank you.
using a combination of EnumWindows, GetWindowInfo and GetWindowRect does the trick.
bool IsTopMost( HWND hwnd )
{
WINDOWINFO info;
GetWindowInfo( hwnd, &info );
return ( info.dwExStyle & WS_EX_TOPMOST ) ? true : false;
}
bool IsFullScreenSize( HWND hwnd, const int cx, const int cy )
{
RECT r;
::GetWindowRect( hwnd, &r );
return r.right - r.left == cx && r.bottom - r.top == cy;
}
bool IsFullscreenAndMaximized( HWND hwnd )
{
if( IsTopMost( hwnd ) )
{
const int cx = GetSystemMetrics( SM_CXSCREEN );
const int cy = GetSystemMetrics( SM_CYSCREEN );
if( IsFullScreenSize( hwnd, cx, cy ) )
return true;
}
return false;
}
BOOL CALLBACK CheckMaximized( HWND hwnd, LPARAM lParam )
{
if( IsFullscreenAndMaximized( hwnd ) )
{
* (bool*) lParam = true;
return FALSE; //there can be only one so quit here
}
return TRUE;
}
bool bThereIsAFullscreenWin = false;
EnumWindows( (WNDENUMPROC) CheckMaximized, (LPARAM) &bThereIsAFullscreenWin );
edit2: updated with tested code, which works fine here for MediaPlayer on Windows 7. I tried with GetForeGroundWindow instead of the EnumWindows, but then the IsFullScreenSize() check only works depending on which area of media player the mouse is in exactly.
Note that the problem with multimonitor setups mentioned in the comment below is still here.
in my oppinion a very little improvement
bool AreSameRECT (RECT& lhs, RECT& rhs){
return (lhs.bottom == rhs.bottom && lhs.left == lhs.left && lhs.right == rhs.right && lhs.top == rhs.top) ? true : false;
}
bool IsFullscreenAndMaximized(HWND hWnd)
{
RECT screen_bounds;
GetWindowRect(GetDesktopWindow(), &screen_bounds);
RECT app_bounds;
GetWindowRect(hWnd, &app_bounds);
if(hWnd != GetDesktopWindow() && hWnd != GetShellWindow()) {
return AreSameRECT(app_bounds, screen_bounds);
}
return false;
}
And thanks to priviose answer
BOOL CALLBACK CheckFullScreenMode ( HWND hwnd, LPARAM lParam )
{
if( IsFullscreenAndMaximized(GetForegroundWindow()) )
{
* (bool*) lParam = true;
std::cout << "true";
return FALSE;
}
return TRUE;
}
int main() {
bool bThereIsAFullscreenWin = false;
EnumWindows( (WNDENUMPROC) CheckFullScreenMode, (LPARAM) &bThereIsAFullscreenWin );
}