How I can get a window's descriptor if I know only a part of its title and its className?
FindWindow() requires the full title. Use EnumWindows(), or GetWindow()in a loop, to enumerate through all available windows, calling GetClassName() and GetWindowText()on each one and compare the values to your search criteria until you find a match.
Something like this:
BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam ) {
wchar_t lpClassName[128] = {0};
MYSTRUCT* MS_INFO = ( MYSTRUCT* )lParam;
GetClassName( hwnd, lpClassName, _countof( lpClassName ) );
if( strstr( lpClassName, MS_INFO -> lpClassName ) ) {
wchar_t lpWindowName[128] = {0};
GetWindowText( hwnd, lpWindowName, _countof( lpWindowName ) );
if( strstr( lpWindowName, MS_INFO -> lpWindowName ) ) {
...
}
}
}
Related
I have a WINAPI application and I want to start it by drag and drop of a file onto the Icon of my application.
The main window is created with
hWnd = CreateWindow("app-name",
"",
WS_OVERLAPPEDWINDOW
| WS_CLIPSIBLINGS
| WS_EX_ACCEPTFILES,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
NULL, NULL, hInstance, NULL);
and has a WndProc with
static LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
DragAcceptFiles(hWnd, TRUE);
// etc (other controls and windows created here)
}
break;
case WM_DROPFILES:
{
char filename[MAX_PATH];
HDROP hDropInfo = (HDROP) wParam;
DragQueryFile(hDropInfo, 0, filename, MAX_PATH);
// etc open file...
}
break;
The problem is that when I drag and drop a file from the Explorer onto my program Icon, the program is started, but I don't receive any WM_DROPFILES message. That is also the case if I configure the file-type to "open with" my program - it's started but no WM_DROPFILES is received.
But once the program is initialized I can drag a drop a file into some of its windows, and then I get the WM_DROPFILES message as I expect it.
What am I doing wrong?
Thanks for advice!
BR Alfred
As mentioned, you can use the lpCmdLine argument of WinMain function:
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
// remove double quotes from filename with spaces
if( lpCmdLine[0] == '"' ) {
lpCmdLine++;
lpCmdLine[strlen(lpCmdLine)-1] = 0;
}
printf("%s\n",lpCmdLine);
// ...
}
I'm trying to use win32api on user32.dll to get mouse wheel input.
I tried the following:
#state = Win32API.new('user32','DefWindowProc',['i'],'i')
p #state.call(0x0800)
But it keeps returning 0 no matter what I do with my mouse wheel.
I thought something is wrong with my mouse, so I tried to do:
#state = Win32API.new('user32','GetKeyState',['L'],'L')
p #state.call(0x01) #left key
p #state.call(0x02) #right key
It worked, so I'm not sure what's wrong with the mouse wheel.
Regards
Edit 2/20/2014:
I tried to do the following:
GetActiveWindow = Win32API.new('user32','GetForegroundWindow','','i')
DefWindowProc = Win32API.new('user32','DefWindowProc','iiii','i')
DefWindowProc.call(GetActiveWindow.call,
Then, I got stuck with the UINT / Message (2nd argument).
Edit 2/20/2014:
I found the WM_MOUSEWHEEL message
Latest revision:
GetActiveWindow = Win32API.new('user32','GetForegroundWindow','','i')
DefWindowProc = Win32API.new('user32','DefWindowProc','iiii','i')
#WM_MOUSEWHEEL message 0x020A
DefWindowProc.call(GetActiveWindow.call, 0x020A,
Now I just need to figure out the 3rd and 4th argument.
As I don't know Ruby, I will give here a solution in C/C++ using only standard Win32 APIs. If you can call Win32 APIs from Ruby, that will work.
Note that the solution involves "callback" and "pointer". I know that's possible in Python (for example, with the ctypes module) and hope that same thing is possible with Ruby.
Register a Window Class and create a Window from that class, the window will be a Message-Only Window, so it will be invisible, with no GUI.
Use the RegisterRawInputDevices API to ask for raw events from mouse devices.
Set up a message loop, with the standard GetMessage/DispatchMessage combo.
Process the sent WM_INPUT message in your Window Procedure
4.1. Allocate memory for the raw datas
4.2. Retrieve the raw datas
4.3. Filter for mouse event and wheel datas
4.4. Process (I just print the wheel delta)
4.5. Free allocated memory.
Below, full source code. Build with VS2012 Express on Windows 7.
#include <Windows.h>
#include <stdio.h>
LRESULT CALLBACK MyWindowProc( HWND, UINT, WPARAM, LPARAM );
int main( void ) {
WNDCLASS WndClass;
memset( &WndClass, 0, sizeof( WndClass ) );
WndClass.hInstance = GetModuleHandle( NULL );
WndClass.lpszClassName = L"MyRawInputClass";
WndClass.lpfnWndProc = MyWindowProc;
RegisterClass( &WndClass );
HWND hWnd = CreateWindow( WndClass.lpszClassName, NULL, 0, 0, 0, 0, 0,
HWND_MESSAGE, 0, WndClass.hInstance, 0 );
RAWINPUTDEVICE RawInputDevice;
RawInputDevice.usUsagePage = 0x01; // Generic Desktop Controls
RawInputDevice.usUsage = 0x02; // Mouse
RawInputDevice.dwFlags = RIDEV_INPUTSINK;
RawInputDevice.hwndTarget = hWnd;
BOOL bWin32Success = RegisterRawInputDevices( &RawInputDevice, 1,
static_cast<UINT>( sizeof( RAWINPUTHEADER ) ) );
BOOL bRet;
MSG msg;
while( ( bRet = GetMessage( &msg, hWnd, 0, 0 ) ) != 0 ) {
if (bRet != -1) {
DispatchMessage(&msg);
}
}
// NO GUI, UNREACHABLE
DestroyWindow( hWnd );
UnregisterClass( WndClass.lpszClassName, WndClass.hInstance );
return 0;
}
LRESULT CALLBACK MyWindowProc( HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam ) {
switch ( uiMsg ) {
case WM_INPUT: {
UINT dwSize;
HRAWINPUT hRawInput = reinterpret_cast<HRAWINPUT>( lParam );
UINT uiRetCode = GetRawInputData( hRawInput, RID_INPUT, NULL, &dwSize,
static_cast<UINT>( sizeof( RAWINPUTHEADER ) ) );
if ( uiRetCode != 0xffffffff ) {
LPBYTE lpb = new BYTE[ dwSize ];
uiRetCode = GetRawInputData( hRawInput, RID_INPUT, lpb, &dwSize,
static_cast<UINT>( sizeof( RAWINPUTHEADER ) ) );
if ( uiRetCode > 0 ) {
RAWINPUT* praw = reinterpret_cast<RAWINPUT*>( lpb );
if ( praw->header.dwType == RIM_TYPEMOUSE ) {
if ( praw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL ) {
signed int siDelta = static_cast<SHORT>( praw->data.mouse.usButtonData );
printf( "WHEEL EVENT: Delta = %d\n", siDelta );
}
}
}
delete[] lpb;
}
break;
} // WM_INPUT
default:
return DefWindowProc( hWnd, uiMsg, wParam, lParam );
}
return 0;
}
I'm using MS visual c++ 2010 express to write a notepad program. I need to be able to save files from my tabbed interface ( each edit control is stored into a vector ). I can't seem to figure out how to save, depending on which edit control is visible to the user ( active tab ). Everything I've tried so far either doesn't save the contents or only saves from the first edit control. When the user adds a new file to the tabbed interface, it added that edit control to the back of the vector. This is my latest attempt:
std::vector<HWND>vect;
BOOL SaveTextFileFromEdit( HWND hEdit, LPCTSTR pszFileName )
{
HANDLE hFile;
BOOL bSuccess = FALSE;
hFile = CreateFile( pszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile != INVALID_HANDLE_VALUE )
{
DWORD dwTextLength = GetWindowTextLength( hEdit );
if( dwTextLegth > 0 )
{
DWORD dwBufferSize = dwTextLength + 1;
LPSTR pszText = ( LPSTR )GlobalAlloc( GPTR, dwBufferSize );
if( pszText != NULL )
{
if( GetWindowText( hEdit, pszText, dwBufferSize ) )
{
DWORD dwWritten;
if( WriteFile( hFile, pszText, dwTextLength, &dwWritten, NULL ) )
bSuccess = TRUE;
}
GlobalFree( pszText );
}
}
CloseHandle( hFile );
}
return bSuccess;
}
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
case WM_COMMAND:
switch( LOWORD( wParam ) )
{
case ID_FILE_SAVEAS:
{
OPENFILENAME ofn;
char szFileName[ MAX_PATH ] = "";
ZeroMemory( &ofn, sizeof( ofn ) );
ofn.lStructSize = sizeof( ofn );
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrDefExt = "txt";
ofn.flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
if( GetSaveFileName( &ofn ) )
{
HWND hEdit, hTabs;
hTabs = GetDlgItem( hwnd, IDC_MAIN_TAB );
int curTab = TabCtrl_GetCurSel( hTabs );
hEdit = GetDlgItem( hTabs, IDC_MAIN_EDIT );
// This is what i did have: hEdit = GetDlgItem( vect[ curTab ], IDC_MAIN_EDIT );
// Which wasn't saving anything
if( SaveTextFileFromEdit( hEdit, szFileName ) )
{
// EVERYTHING IS GOOD
}
}
}
break;
}
break;
}
return 0;
}
If the vector has each edit control's HWND then you don't need GetDlgItem at all: You already have the HWND that it would return.
hEdit = vect[ curTab ];
Its been asked before, but what I found was either mfc, or was not for a superclassed control, or maybe my keyword choice was not good(my vocabulary is limited)
I am developing in pure win32 and c++ in Devc++. I have a few Edit controls superclassed where Tab key presses and Return key presses are controled, but whenever I press Tab there is this Ding sound which is very annoying, not sure it is there because I am doing something wrong or what. Anyway, how do I remove it ?
This is my first attempt at superclassing, so if you have any other advice regarding the code, please let me know
Code:
LRESULT APIENTRY EditSuperClassWndProc ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch (message)
{
case WM_KEYDOWN:
if ( isMyScreen )
{
if ( (int)wParam == VK_RETURN )
{
DWORD wparam = MAKELONG( 0, BN_CLICKED );
SendMessage( GetParent( hwnd ), WM_COMMAND, (WPARAM)wparam, (LPARAM)hButton );
}
else if ( (int)wParam == VK_TAB )
{
HWND nextInLine;
if( hwnd == hEditP )
nextInLine = hEditL;
else if ( hwnd == hEditL )
nextInLine = hEditP;
SendMessage( nextInLine, EM_SETSEL, (WPARAM)0, (LPARAM)-1 );
SetFocus( nextInLine );
}
else
{
return CallWindowProc( oldWndProc, hwnd, message, wParam, lParam );
}
}
return CallWindowProc( oldWndProc, hwnd, message, wParam, lParam );
break;
default:
return CallWindowProc( oldWndProc, hwnd, message, wParam, lParam );
}
}
Try adding the following code to your switch block:
case WM_CHAR:
if (wParam == VK_TAB)
{
return 0;
}
else
{
return CallWindowProc(oldWndProc, hwnd, message, wParam, lParam );
}
break;
I have a Windows app that uses the AppBar API to install as an application bar at the top of the screen (similar to the Windows task bar itself). This works great and the desktop size is adjusted accordingly, so my application is always visible.
However, if the user choose 'Show Desktop' (Windows+D), my application is hidden. Does anyone know of a way to trap 'Show Desktop' so I can ensure my application stays visible (I assume that Windows enumerates all top-level windows and hides them with ShowWindow(SW_HIDE).
Use the following code and pass the window handle to the function while form load.
Hopefully this resolves your problem.
public void SetFormOnDesktop(IntPtr hwnd)
{
IntPtr hwndf = hwnd;
IntPtr hwndParent = FindWindow("ProgMan", null);
SetParent(hwndf, hwndParent);
}
I was under the impression that setting the window as a topmost window (via SetWindowPos and the HWND_TOPMOST flag) prevented the desktop from covering it. Windows+D goes through minimizing all windows, and then covering up those that can't be minimized by raising the desktop in the z-order (well, it did at one point anyway). I belive you can make a window unminimizable by not passing WS_MINIMIZEBOX to CreateWindowEx, or using WS_EX_TOOLWINDOW though I'm not 100% on that part.
A much heavier handed approach would be to hook the global keyboard using SetWindowsHookEx and a KeyboardProc. This will have a deleterious effect on the user experience.
I went and coded up a really simple example of what I'm talking about. The following code makes a window that is not minimized OR covered by a user hitting Windows+D. Note that on Windows 7, gadgets on the desktop can still be brought above it; which I can't really explain.
#include <windows.h>
#include <tchar.h>
#define WIN_TITLE _T("Resists Win+D Window")
#define WIN_CLASS _T("Resists Win+D Class")
LRESULT CALLBACK CustomWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//Special behavior goes here
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
HWND CreateMainWindow(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = CustomWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = WIN_CLASS;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
if (!RegisterClassEx(&wcex))
{
exit(1);
}
HWND hWnd = CreateWindowEx(
WS_EX_TOOLWINDOW,
WIN_CLASS,
WIN_TITLE,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
500,
100,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
exit(1);
}
return hWnd;
}
/*
Main entry point
*/
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hwnd = CreateMainWindow(hInstance);
ShowWindow(hwnd, nCmdShow);
SetWindowPos(hwnd, HWND_TOPMOST, -1, -1, -1, -1, SWP_NOMOVE | SWP_NOSIZE);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
In your ABN_FULLSCREENAPP notification, you need to determine whether the window occupying the working area is the Desktop and if so, ignore the ABN_FULLSCREENAPP message.
P.S. As an alternative implementation, consider the commercial ShellAppBar component.
In addition to the answer of JKS, here is working code for VB.NET, assuming you already converted your form to an appbar. You need to p/invoke the functions FindWindow and SetFormOnDesktop.
'In your form
Public Sub New()
'Stuff
SetFormOnDesktop(Me.Handle)
'More stuff
End Sub
'In your form or somewhere else.
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindow( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function SetParent(_
ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
End Function
Public Sub SetFormOnDesktop(hwnd As IntPtr)
Dim hwndf As IntPtr = hwnd
Dim hwndParent As IntPtr = FindWindow("ProgMan", Nothing)
SetParent(hwndf, hwndParent)
End Sub