I want to write a WMI application using windows API and COM library in Qt.
I include <qt_windows.h> to access windows API , I tried this before in Visual Studio.
But when I include Wbemidl.h to declare a IWbemLocator variable, the compiler give me the following error :
error: Wbemidl.h: No such file or directory
This is a section of my code :
HRESULT hResult = S_OK; // Result of initializing com library
BOOL bIsComLibUninit = FALSE; // A flag that determine if com library is loaded
// Initialize COM library
hResult = CoInitializeEx(0, COINIT_MULTITHREADED);
// If a previous call of CoInitializeEx occured in this thread
if(hResult == RPC_E_CHANGED_MODE)
{
OleUninitialize();
bIsComLibUninit = TRUE;
}
else if(hResult == S_OK)
{
bIsComLibUninit = TRUE;
}
// If COM library uninitialized
if(bIsComLibUninit == TRUE)
{
// Initialize COM library
hResult = CoInitializeEx(0, COINIT_MULTITHREADED);
if(hResult == S_OK)
{
// Initialize security
hResult = CoInitializeSecurity(NULL, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE, NULL);
if(hResult == S_OK)
{
IWbemLocator *pLoc = NULL;
CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
// Do stuffs
}
}
// Uninitialize COM library
CoUninitialize();
}
Error message tells that compiler can't find the header file.
Try to find the "Wbemidl.h" in your location(e.g. the Path in my local: C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\um), and add the PATH to your compiler. Also don't forget the .lib reference.
If you can't find this header file, try to download sdk from here, select one which suits you:
I am trying to get clipboard data via QClipboard. Here is my code:
void MainWindow::getText()
{
QClipboard *clipboard = QGuiApplication::clipboard();
const QMimeData *mime = clipboard->mimeData (QClipboard::Selection);
QString originalText = clipboard->text(); // no crashes in windows
//QString originalText = mime->text (); //this line causing program crash
.................
}
getText() called every 5 second using QTimer. The above code works perfectly in linux, when I try to run the code in windows 7 it crashed.
clipboard->mimeData can be null, so you might want to either cache the previous state, or do the following:
QString originalText = mime ? mime->text() : QString();
Windows doesn't support QClipboard::Selection, that's why application crashes everytime. Here is how I solved it
QString originalText;
if(QSysInfo::productType() == "windows") {
QString clipboard = QApplication::clipboard()->text();
originalText = clipboard;
} else {
// for linux
QClipboard *clipboard = QGuiApplication::clipboard();
const QMimeData *mime = clipboard->mimeData (QClipboard::Selection);
originalText = mime->text ();
}
I'm new to Qt, and I'm trying to display the Ovi map.
Unfortunately, my program just crashes. Here is my code:
MapView::MapView(QWidget *parent, const char *name) {
mappingManager = 0;
QGeoServiceProvider *serviceProvider = new QGeoServiceProvider("nokia");
// QGeoSearchManager *searchManager = 0;
// QGeoServiceProvider serviceProvider("nokia");
//QGeoRoutingManager *routingManager = 0;
//routingManager = serviceProvider.routingManager();
if (serviceProvider->error() == QGeoServiceProvider::NoError) {
mappingManager = serviceProvider->mappingManager();
// searchManager = serviceProvider.searchManager();
QGraphicsScene *scene = new QGraphicsScene(this);
QGraphicsView *view = new QGraphicsView(scene, this);
mapGraphics = new QGraphicsGeoMap(mappingManager);
mapGraphics->setMapType(QGraphicsGeoMap::StreetMap);
mapGraphics->setConnectivityMode(QGraphicsGeoMap::HybridMode);
// scene->addText("Map view");
scene->addItem(mapGraphics);
view->show();
} else {
QMessageBox::information(this, "Map", "Service provider error");
}
}
I've commented out the line which I think is causing the crash - the scene->addItem(mapGraphics);
How should I add the mapGraphics so I can see it on screen?
I'd really appreciate a hand with this.
Thankyou in advance, J
Have a look at Maps Demo tutorial.
The source code is found in {QtSDK}\Examples\4.7\mobile\mapsdemo\ or on qt.gitorious.org
This problem has been afflicting me for quite a while and it's been really annoying.
Every time I login after a reboot/power cycle the explorer takes some time to show up.
I've taken the step of waiting for all the services to boot up and then I login, but it doesn't make any difference.
The result is always the same: Some of the icons do not show up even if the applications have started.
I've dug a bit on the code that makes one application "stick" an icon in there, but is there an API call that one can perform so explorer re-reads all that icon info? Like invalidate or redraw or something of the sort?
Apparently, it looks like Jon was right and it's not possible to do it.
I've followed Bob Dizzle and Mark Ransom code and build this (Delphi Code):
procedure Refresh;
var
hSysTray: THandle;
begin
hSysTray := GetSystrayHandle;
SendMessage(hSysTray, WM_PAINT, 0, 0);
end;
function GetSystrayHandle: THandle;
var
hTray, hNotify, hSysPager: THandle;
begin
hTray := FindWindow('Shell_TrayWnd', '');
if hTray = 0 then
begin
Result := hTray;
exit;
end;
hNotify := FindWindowEx(hTray, 0, 'TrayNotifyWnd', '');
if hNotify = 0 then
begin
Result := hNotify;
exit;
end;
hSyspager := FindWindowEx(hNotify, 0, 'SysPager', '');
if hSyspager = 0 then
begin
Result := hSyspager;
exit;
end;
Result := FindWindowEx(hSysPager, 0, 'ToolbarWindow32', 'Notification Area');
end;
But to no avail.
I've even tried with InvalidateRect() and still no show.
Any other suggestions?
Take a look at this blog entry: REFRESHING THE TASKBAR NOTIFICATION AREA. I am using this code to refresh the system tray to get rid of orphaned icons and it works perfectly.
The blog entry is very informative and gives a great explanation of the steps the author performed to discover his solution.
#define FW(x,y) FindWindowEx(x, NULL, y, L"")
void RefreshTaskbarNotificationArea()
{
HWND hNotificationArea;
RECT r;
GetClientRect(
hNotificationArea = FindWindowEx(
FW(FW(FW(NULL, L"Shell_TrayWnd"), L"TrayNotifyWnd"), L"SysPager"),
NULL,
L"ToolbarWindow32",
// L"Notification Area"), // Windows XP
L"User Promoted Notification Area"), // Windows 7 and up
&r);
for (LONG x = 0; x < r.right; x += 5)
for (LONG y = 0; y < r.bottom; y += 5)
SendMessage(
hNotificationArea,
WM_MOUSEMOVE,
0,
(y << 16) + x);
}
Two important details for anyone using Louis's answer (from REFRESHING THE TASKBAR NOTIFICATION AREA) on Windows 7 or Windows 8:
First, as the answer was reflected to show, the window titled "Notification Area" in XP is now titled "User Promoted Notification Area" in Windows 7 (actually probably Vista) and up.
Second, this code does not clear icons that are currently hidden. These are contained in a separate window. Use the original code to refresh visible icons, and the following to refresh hidden icons.
//Hidden icons
GetClientRect(
hNotificationArea = FindWindowEx(
FW(NULL, L"NotifyIconOverflowWindow"),
NULL,
L"ToolbarWindow32",
L"Overflow Notification Area"),
&r);
for (LONG x = 0; x < r.right; x += 5)
for (LONG y = 0; y < r.bottom; y += 5)
SendMessage(
hNotificationArea,
WM_MOUSEMOVE,
0,
(y << 16) + x);
For anyone who just needs a utility to run to accomplish this, rather than code, I built a simple exe with this update: Refresh Notification Area
Include following code with yours to refresh System Tray.
public const int WM_PAINT = 0xF;
[DllImport("USER32.DLL")]
public static extern int SendMessage(IntPtr hwnd, int msg, int character,
IntPtr lpsText);
Send WM_PAINT Message to paint System Tray which will refresh it.
SendMessage(traynotifywnd, WM_PAINT, 0, IntPtr.Zero);
As far as I know that isn't possible Gustavo - it's up to each application to put its notifyicon in the systray, and ensure it's kept in the right state.
You'll notice sometimes when explorer.exe crashes that certain icons don't reappear - this isn't because their process has crashed, simply that their application hasn't put the notifyicon in the systray when the new instance of explorer.exe started up. Once again, it's the application that's responsible.
Sorry not to have better news for you!
I covered this issue last year on my Codeaholic weblog in an article entitled [Delphi] Updating SysTray.
My solution is a Delphi ActiveX/COM DLL. The download link still works (though for how much longer I don't know as my PLUG membership has lapsed.)
I use the following C++ code to get the window handle to the tray window. Note: this has only been tested on Windows XP.
HWND FindSystemTrayIcons(void)
{
// the system tray icons are contained in a specific window hierarchy;
// use the Spy++ utility to see the chain
HWND hwndTray = ::FindWindow("Shell_TrayWnd", "");
if (hwndTray == NULL)
return NULL;
HWND hwndNotifyWnd = ::FindWindowEx(hwndTray, NULL, "TrayNotifyWnd", "");
if (hwndNotifyWnd == NULL)
return NULL;
HWND hwndSysPager = ::FindWindowEx(hwndNotifyWnd, NULL, "SysPager", "");
if (hwndSysPager == NULL)
return NULL;
return ::FindWindowEx(hwndSysPager, NULL, "ToolbarWindow32", "Notification Area");
}
After lots of times trying I found that there are three issues you must to know:
The parent of hidden tray window is NotifyIconOverflowWindow, other than Shell_TrayWnd.
You shouldn't use caption parameter of FindWindowEx to find a window, because these is lots of langue versions of Windows OS, they are not always be the same title Obviously.
Use spy++ of Visual Studio to find or make assurance what you want.
So, I changed code from #Stephen Klancher and #Louis Davis, thank you guys.
The following code worked for me.
#define FW(x,y) FindWindowEx(x, NULL, y, L"")
void RefreshTaskbarNotificationArea()
{
HWND hNotificationArea;
RECT r;
GetClientRect(hNotificationArea = FindWindowEx(FW(NULL, L"NotifyIconOverflowWindow"), NULL, L"ToolbarWindow32", NULL), &r);
for (LONG x = 0; x < r.right; x += 5)
{
for (LONG y = 0; y < r.bottom; y += 5)
{
SendMessage(hNotificationArea, WM_MOUSEMOVE, 0, (y << 16) + x);
}
}
}
#Skip R, and anyone else wanting to do this in C, with this code verified compiled in a recent (most recent) mingw on Windows 10 64 bit (but with the mingw 32 bit package installed), this seems to work in Windows XP / 2003 to get rid of stale notification area icons.
I installed mingw via Chocolatey, like this:
choco install mingw --x86 --force --params "/exception:sjlj"
(your mileage may vary on that, on my system, the compiler was then installed here:
C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw32\bin\gcc.exe
and then a simple
gcc refresh_notification_area.c
yielded an a.exe which solved a stale notification area icon problem I was having on Windows 2003 (32 bit).
The code, adapted from #Stephen Klancher above is (note this may only work on Windows XP/2003, which fulfilled my purposes):
#include <windows.h>
#define FW(x,y) FindWindowEx(x, NULL, y, "")
int main ()
{
HWND hNotificationArea;
RECT r;
//WinXP
// technique found at:
// https://stackoverflow.com/questions/74723/can-you-send-a-signal-to-windows-explorer-to-make-it-refresh-the-systray-icons#18038441
GetClientRect(
hNotificationArea = FindWindowEx(
FW(FW(FW(NULL, "Shell_TrayWnd"), "TrayNotifyWnd"), "SysPager"),
NULL,
"ToolbarWindow32",
"Notification Area"),
&r);
for (LONG x = 0; x < r.right; x += 5)
for (LONG y = 0; y < r.bottom; y += 5)
SendMessage(
hNotificationArea,
WM_MOUSEMOVE,
0,
(y << 16) + x);
return 0;
}
Powershell solution, put this in your script
Add-Type -AssemblyName System.Windows.Forms
Add-Type #"
using System;
using System.Runtime.InteropServices;
public struct RECT {
public int left;
public int top;
public int right;
public int bottom;
}
public class pInvoke {
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll")]
public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
public static void RefreshTrayArea() {
IntPtr systemTrayContainerHandle = FindWindow("Shell_TrayWnd", null);
IntPtr systemTrayHandle = FindWindowEx(systemTrayContainerHandle, IntPtr.Zero, "TrayNotifyWnd", null);
IntPtr sysPagerHandle = FindWindowEx(systemTrayHandle, IntPtr.Zero, "SysPager", null);
IntPtr notificationAreaHandle = FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "Notification Area");
if (notificationAreaHandle == IntPtr.Zero) {
notificationAreaHandle = FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "User Promoted Notification Area");
IntPtr notifyIconOverflowWindowHandle = FindWindow("NotifyIconOverflowWindow", null);
IntPtr overflowNotificationAreaHandle = FindWindowEx(notifyIconOverflowWindowHandle, IntPtr.Zero, "ToolbarWindow32", "Overflow Notification Area");
RefreshTrayArea(overflowNotificationAreaHandle);
}
RefreshTrayArea(notificationAreaHandle);
}
private static void RefreshTrayArea(IntPtr windowHandle) {
const uint wmMousemove = 0x0200;
RECT rect;
GetClientRect(windowHandle, out rect);
for (var x = 0; x < rect.right; x += 5)
for (var y = 0; y < rect.bottom; y += 5)
SendMessage(windowHandle, wmMousemove, 0, (y << 16) + x);
}
}
"#
Then use [pInvoke]::RefreshTrayArea() to reset