这个。。我做的托盘有问题啊!!!
是这样。。问题1:当前焦点在窗口上,右键托盘图标,托盘的菜单晃了一下(或者没反应),窗口的焦点失去了,(XP下)标题栏由天蓝色变成蓝灰色。。。。。再次右键托盘,菜单成功出现。。。
问题2:右键的托盘菜单出现之后,菜单不消失,除非(1)选择一个选项(2)单击窗口,使窗口获得焦点,无论是单击其他程序窗口还是桌面,无论左键还是右键,统统不好用,菜单就是不消失。。。
请问这两个问题怎么解决??
我用结果。。。代码显示出来不换行。。。只好不用那玩意排版了。。。
上代码。。就是以前WY发的程序代码改的。。封了个类。。
.h
#ifndef _MainWindow_H_
#define _MainWindow_H_
#include <Windows.h>
#include "resource.h"
// 系统托盘相关
#define WM_USER_TRAY WM_USER+1
#define IDM_OPEN 1
#define IDM_HIDE 2
#define IDM_SETUP 3
#define IDM_EXIT 4
class MainWindow
{
private:
HWND hWnd;
HINSTANCE hInstance;
char cClassName;
char cTitleName;
int iWidth;
int iHeight;
NOTIFYICONDATAA sIconData;
HMENU hPopupMenu;
static MainWindow* pThis;
public:
MainWindow();
~MainWindow();
bool Init(HINSTANCE hInst);
bool Render();
bool Update();
bool Release();
bool SetClassName(const char* cpcName);
bool SetTitleName(const char* cpcName);
bool SetWidgetSize(int width, int height);
HMENU GetPopupMenu() {return hPopupMenu;}
static LRESULT CALLBACK MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
#endif .cpp
#include "MainWindow.h"
MainWindow::MainWindow():hWnd(0), hInstance(0), iWidth(0), iHeight(0), hPopupMenu(0)
{
memset(cClassName, 0, 32);
memset(cTitleName, 0, 32);
memset(&sIconData, 0, sizeof(NOTIFYICONDATAA));
}
MainWindow::~MainWindow()
{
Release();
}
bool MainWindow::Init(HINSTANCE hInst)
{
if (hInst == 0) return false;
hInstance = hInst;
pThis = this;
// 创建窗口
WNDCLASSEXA wndClass;
wndClass.cbSize = sizeof(wndClass);
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = &MainWindow::MsgProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = NULL;//LoadIcon(hInstance, MAKEINTRESOURCE(IDI_NORMAL));
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = NULL;//MAKEINTRESOURCE(IDC_DAHUAXY2);
wndClass.lpszClassName = cClassName;
wndClass.hIconSm = NULL;//LoadIcon(wndClass.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassExA(&wndClass);
RECT rcWnd = { 0, 0, iWidth, iHeight};
hWnd = CreateWindowExA(0,
cClassName,
cTitleName,//WND_TITLENAME
WS_OVERLAPPEDWINDOW,
(GetSystemMetrics(SM_CXSCREEN)-iWidth)/2, // SM_CXSCREEN:以像素为单位的屏幕的宽度
(GetSystemMetrics(SM_CYSCREEN)-iHeight)/2, // SM_CYSCREEN:以像素为单位的屏幕的高度
(rcWnd.right-rcWnd.left), (rcWnd.bottom-rcWnd.top),
NULL,
NULL,
hInstance,
NULL);
if (hWnd == 0)
{
UnregisterClassA(cClassName, hInst);
return false;
}
ShowWindow(hWnd, SW_NORMAL);
//ShowWindow(hWnd, SW_HIDE);
UpdateWindow(hWnd);
sIconData.cbSize = sizeof(NOTIFYICONDATAA);
sIconData.hWnd = hWnd;
sIconData.uID = IDI_ICON1;
sIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
sIconData.uCallbackMessage = WM_USER_TRAY;
sIconData.hIcon = LoadIcon(NULL, IDI_APPLICATION);
lstrcpyA(sIconData.szTip, "Desktop Widget made by secondsen / 2nDs");
Shell_NotifyIconA(NIM_ADD, &sIconData);
// 创建系统托盘右键弹出菜单
hPopupMenu = CreatePopupMenu();
AppendMenuA(hPopupMenu, MF_STRING, IDM_OPEN, "打开");
AppendMenuA(hPopupMenu, MF_STRING, IDM_HIDE, "隐藏");
AppendMenuA(hPopupMenu, MF_STRING, IDM_SETUP, "设置");
AppendMenuA(hPopupMenu, MF_STRING, IDM_EXIT, "退出");
return true;
}
bool MainWindow::Release()
{
UnregisterClassA(cClassName, hInstance);
return true;
}
bool MainWindow::Render()
{
}
bool MainWindow::Update()
{
}
bool MainWindow::SetClassName(const char* cpcName)
{
if (cpcName)
{
strcpy(cClassName, cpcName);
return true;
}
return false;
}
bool MainWindow::SetTitleName(const char* cpcName)
{
if (cpcName)
{
strcpy(cTitleName, cpcName);
return true;
}
return false;
}
bool MainWindow::SetWidgetSize(int width, int height)
{
if (width <= 1 || height <= 1) return false;
iWidth = width;
iHeight = height;
return true;
}
LRESULT MainWindow::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SIZE:
if (wParam == SIZE_MINIMIZED) ShowWindow(hWnd, SW_HIDE);
break;
case WM_COMMAND:
{
WORD hWord = HIWORD(wParam);
WORD lWord = LOWORD(wParam);
switch(lWord)
{
case IDM_OPEN:
{
// 隐藏系统托盘
//SetSystemTray(&g_IconData, false);
ShowWindow(hWnd, SW_SHOW);
SendMessageA(hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
}
break;
case IDM_EXIT:
Shell_NotifyIconA(NIM_DELETE, &(pThis->sIconData));
ShowWindow(hWnd, SW_HIDE);
PostQuitMessage(0);
break;
case IDM_HIDE:
SendMessage(hWnd,WM_SYSCOMMAND,SC_MINIMIZE,0);
break;
}
}
break;
case WM_USER_TRAY:
{
UINT msg = (UINT)lParam;
UINT id = (UINT)wParam;
if (id == IDI_ICON1)
{
if (msg == WM_LBUTTONDOWN)
{
ShowWindow(hWnd, SW_SHOW);
SendMessageA(hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
}
// 当用户在气球提示上或托盘图标上单击鼠标(此时气球处于显示状态)时
if (msg == NIN_BALLOONUSERCLICK)
{
}
if (msg == WM_RBUTTONDOWN)
{
POINT pos;
::GetCursorPos(&pos);
TrackPopupMenu(pThis->hPopupMenu, TPM_RIGHTALIGN, pos.x, pos.y, NULL, hWnd, NULL);
}
}
}
break;
case WM_DESTROY:
Shell_NotifyIconA(NIM_DELETE, &(pThis->sIconData));
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
} main.cpp
#include "MainWindow.h"
#include <malloc.h>
MainWindow* MainWindow::pThis = 0;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int nCmdShow)
{
MainWindow* pMainWindow = new MainWindow ;
pMainWindow->SetClassName("SetupWindow");
pMainWindow->SetTitleName("DesktopWidget");
pMainWindow->SetWidgetSize(800,600);
pMainWindow->Init(hInstance);
MSG msg;
memset(&msg, 0, sizeof(msg));
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// 帧开始
float timeInOneFps = 1000.0f/60.0f; // 每秒60帧,则1帧就是约16毫秒
DWORD timeBegin = GetTickCount();
//MainLoop();
// 限帧
DWORD timeTotal = GetTickCount() - timeBegin;
if (timeTotal < timeInOneFps)
{
Sleep(DWORD(timeInOneFps-timeTotal));
}
}
}
delete pMainWindow ;
return 1;
} 以上,完毕 代码太多,不知道是怎么回事,还有我的系统是win7,没法判断。
所以重写了个小例子,随便看看吧。
用gcc 4.7.2编译的,不知到怎么回事,这个4.7.2中使用GetSystemMetrics总取不到正确的值,所以就显示在左上角了。 代码就一个文件
#include <windows.h>
#include <gdiplus.h>
unsigned int iconmessage = RegisterWindowMessage("IconNotify");
#define MYWM_ICON (WM_APP+100)
HMENU popMenu;
NOTIFYICONDATA nid;
struct YY
{
const char* szClassName;
HWND hwnd;
MSG messages;
WNDCLASSEX wincl;
ULONG_PTR gdiplusStartupToken;
YY() :szClassName("YY")
{}
~YY()
{
Gdiplus::GdiplusShutdown(gdiplusStartupToken); //消毁gdi+
}
void InitWin(HINSTANCE hThisInstance)
{
//初始化gdi+
Gdiplus::GdiplusStartupInput gdiInput;
Gdiplus::GdiplusStartup(&gdiplusStartupToken,&gdiInput,NULL);
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure;
wincl.style = CS_DBLCLKS;
wincl.cbSize = sizeof (WNDCLASSEX);
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
if (!RegisterClassEx (&wincl))
return;
hwnd = CreateWindowEx (
WS_EX_LAYERED|WS_EX_TOOLWINDOW|WS_EX_TOPMOST,
szClassName,
"YY Test",
WS_OVERLAPPEDWINDOW,
0,
0,
450,
600,
NULL,
NULL,
hThisInstance,
NULL
);
ShowWindow (hwnd, SW_SHOWNORMAL);
MoveWindow(hwnd, 0, 0, 450, 600, TRUE);
SetPic(L"alice.png");
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hwnd;
nid.uID = iconmessage;
nid.uFlags = NIF_ICON|NIF_MESSAGE;
nid.hIcon = LoadIcon(NULL, IDI_APPLICATION);
nid.uCallbackMessage = MYWM_ICON;
}
int Run()
{
while (GetMessage (&messages, NULL, 0, 0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return messages.wParam;
}
void SetPic(const wchar_t* fn)
{
RECT wndRect;
GetWindowRect(hwnd,&wndRect);
SIZE wndSize = {wndRect.right-wndRect.left, wndRect.bottom-wndRect.top};
HDC hdc = GetDC(hwnd);
HDC memDC = CreateCompatibleDC(hdc);
HBITMAP memBitmap = CreateCompatibleBitmap(hdc, wndSize.cx, wndSize.cy);
SelectObject(memDC,memBitmap);
Gdiplus::Image image(fn);
Gdiplus::Graphics graphics(memDC);
graphics.DrawImage(&image, 0, 0, wndSize.cx,wndSize.cy);
HDC screenDC = GetDC(NULL);
POINT ptSrc = {0,0};
BLENDFUNCTION blendFunction;
blendFunction.AlphaFormat = AC_SRC_ALPHA;
blendFunction.BlendFlags = 0;
blendFunction.BlendOp = AC_SRC_OVER;
blendFunction.SourceConstantAlpha = 255;
UpdateLayeredWindow(hwnd,screenDC,&ptSrc,&wndSize,memDC,&ptSrc,0,&blendFunction,2);
DeleteDC(memDC);
DeleteObject(memBitmap);
ReleaseDC(hwnd, hdc);
ReleaseDC(0, screenDC);
}
static LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
popMenu = CreatePopupMenu();
AppendMenu(popMenu, MF_STRING, 1, "隐藏");
AppendMenu(popMenu, MF_STRING, 2, "恢复");
AppendMenu(popMenu, MF_STRING, 3, "关于");
AppendMenu(popMenu, MF_STRING, 4, "退出");
break;
case WM_RBUTTONDOWN:
POINT pt;
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
ClientToScreen(hwnd, &pt);
TrackPopupMenu(popMenu, TPM_RIGHTALIGN, pt.x, pt.y, 0, hwnd, NULL);
break;
case MYWM_ICON:
if(wParam == iconmessage)
{
switch(lParam)
{
case WM_LBUTTONDBLCLK: //左双击
ShowWindow(hwnd, SW_SHOWNORMAL);
Shell_NotifyIcon(NIM_DELETE, &nid);
break;
case WM_RBUTTONDOWN: //右单击
POINT pt;
GetCursorPos(&pt);
SetForegroundWindow(hwnd);
TrackPopupMenu(popMenu, TPM_RIGHTALIGN, pt.x, pt.y, 0, hwnd, NULL);
break;
case WM_MOUSEMOVE: //悬停
break;
}
}
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case 1:
ShowWindow(hwnd, SW_HIDE);
Shell_NotifyIcon(NIM_ADD, &nid);
break;
case 2:
ShowWindow(hwnd, SW_SHOWNORMAL);
Shell_NotifyIcon(NIM_DELETE, &nid);
break;
case 3:
MessageBox(hwnd, "用gdi+实现透明不规则界面", "关于", MB_OK);
break;
case 4:
PostQuitMessage(0);
break;
}
break;
case WM_DESTROY:
DestroyMenu(popMenu);
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
};
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
YY yy;
yy.InitWin(hThisInstance);
return yy.Run();
}
原来不是GetSystemMetrics失灵,而是描画半透明窗口时由UpdateLayeredWindow 的第3个参数指定位置。前面的CreateWindowEx MoveWindow都没有作用了。 总之,我的问题解决了shawind大真实可靠的人哇
页:
[1]