secondsen 发表于 2012-10-7 23:50:48

这个。。我做的托盘有问题啊!!!

是这样。。
问题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

secondsen 发表于 2012-10-7 23:56:14

.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);
}

secondsen 发表于 2012-10-7 23:56:36

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;
}

secondsen 发表于 2012-10-7 23:59:28

以上,完毕

shawind 发表于 2012-10-10 14:32:18

代码太多,不知道是怎么回事,还有我的系统是win7,没法判断。
所以重写了个小例子,随便看看吧。
用gcc 4.7.2编译的,不知到怎么回事,这个4.7.2中使用GetSystemMetrics总取不到正确的值,所以就显示在左上角了。

shawind 发表于 2012-10-10 14:33:23

代码就一个文件

#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();
}

shawind 发表于 2012-10-11 15:47:06

原来不是GetSystemMetrics失灵,而是描画半透明窗口时由UpdateLayeredWindow 的第3个参数指定位置。前面的CreateWindowEx MoveWindow都没有作用了。

secondsen 发表于 2012-10-11 18:17:20

总之,我的问题解决了shawind大真实可靠的人哇
页: [1]
查看完整版本: 这个。。我做的托盘有问题啊!!!