2017-11-10 6 views
1

私は目に見えるウィンドウがないアプリケーションをトレイアイコンとして作成しようとしています。私はさまざまなチュートリアルと答えをまとめてみようとしましたが、これ以上は得られませんでした。ただし、右クリックが完全に空白の場合、コンテキストメニューが表示されます。また、一度クリックしたものがどのように検出されたらうまくいくのか分かりません。システムトレイのコンテキストメニューブランク

最終目標は、コンテキストメニューで2つのオプションのいずれかをクリックしてDNSサーバーを切り替えることです。

#include <Windows.h> 
#include <shellapi.h> 
#include <tchar.h> 
#include <WinUser.h> 


HINSTANCE gInstance = NULL; 

LRESULT CALLBACK pWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{ 
    WNDCLASSEX wx; 
    HWND hWnd; 
    ZeroMemory(&wx, sizeof(WNDCLASSEX)); 

    wx.cbSize = sizeof(WNDCLASSEX); 
    wx.lpfnWndProc = pWndProc; 
    wx.hInstance = hInstance; 
    wx.lpszClassName = (LPCWSTR)"DNSChanger"; 
    RegisterClassEx(&wx); 
    CreateWindowEx(0, (LPCWSTR)"DNSChanger", (LPCWSTR)"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); 
    gInstance = hInstance; 

    MSG stMsg; 
    while (GetMessage(&stMsg, NULL, 0, 0) > 0) 
    { 
     TranslateMessage(&stMsg); 
     DispatchMessage(&stMsg); 
    } 

    return 0; 
} 

LRESULT CALLBACK pWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    NOTIFYICONDATA niData; 
    ZeroMemory(&niData, sizeof(NOTIFYICONDATA)); 

    switch (uMsg) 
    { 
     case WM_CREATE: 
     { 
      niData.cbSize = sizeof(NOTIFYICONDATA); 
      niData.uID = 1; 
      niData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; 
      niData.hIcon = LoadIcon(gInstance, MAKEINTRESOURCE(IDI_SHIELD)); 
      niData.hWnd = hWnd; 
      niData.uCallbackMessage = WM_USER + 1; 

      Shell_NotifyIcon(NIM_ADD, &niData); 
     } 
     return 0; 

     case WM_DESTROY: 
     { 
      niData.hWnd = hWnd; 
      Shell_NotifyIcon(NIM_DELETE, &niData); 
     } 
     return 0; 

     case WM_USER + 1: 
     { 
      switch (LOWORD(lParam)) 
      { 
       case WM_RBUTTONUP: 
       { 
        POINT lpClickPoint; 
        HMENU hPopMenu; 

        UINT uFlag = MF_BYPOSITION | MF_UNCHECKED | MF_STRING; 
        GetCursorPos(&lpClickPoint); 
        hPopMenu = CreatePopupMenu(); 
        InsertMenu(hPopMenu, 0xFFFFFFFF, MF_BYPOSITION | MF_STRING, WM_USER + 1, _T("Exit")); 
        SetForegroundWindow(hWnd); 
        TrackPopupMenu(hPopMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_BOTTOMALIGN, lpClickPoint.x, lpClickPoint.y, 0, hWnd, NULL); 
       } 
      } 
     } 
    } 
} 

答えて

0

このようなキャストは使用しないでください。(LPCWSTR)"DNSChanger"これは、コンパイラエラーを隠すだけです。プログラムがまったく動作する唯一の理由は、このエラーが2つの異なる場所で繰り返され、取り消されるためです。

L"DNSChanger"と書いてください。

ウィンドウプロシージャを使用すると、アプリケーションを終了したい場合は、PostQuitMessage(0);を含める必要がありWM_DESTROYDefWindowProc(hWnd, uMsg, wParam, lParam);

を返す必要があります。

は一部 WM_COMMANDメッセージとしてIDM_EXITコマンドを送信するメニュー

const int IDM_EXIT = 100; 
... 
InsertMenu(hmenu, 0, MF_BYPOSITION | MF_STRING, IDM_EXIT, L"Exit"); 

メニューで使用するために新しい定数を定義します。以下は推奨される変更の一部です:

HINSTANCE gInstance = NULL; 
const int IDM_EXIT = 100; 
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    static NOTIFYICONDATA niData = { sizeof(NOTIFYICONDATA) }; 

    switch(uMsg) 
    { 
    case WM_CREATE: 
    { 
     niData.uID = 1; 
     niData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; 
     niData.hIcon = LoadIcon(gInstance, IDI_SHIELD); 
     niData.hWnd = hWnd; 
     niData.uCallbackMessage = WM_USER + 1; 
     Shell_NotifyIcon(NIM_ADD, &niData); 
     return 0; 
    } 

    case WM_DESTROY: 
    { 
     niData.hWnd = hWnd; 
     Shell_NotifyIcon(NIM_DELETE, &niData); 
     PostQuitMessage(0); 
     return 0; 
    } 

    case WM_COMMAND: 
    { 
     if(LOWORD(wParam) == IDM_EXIT) 
      PostQuitMessage(0); 
     break; 
    } 

    case WM_USER + 1: 
    { 
     WORD cmd = LOWORD(lParam); 
     if (cmd == WM_RBUTTONUP || cmd == WM_LBUTTONUP) 
     { 
      POINT pt; 
      GetCursorPos(&pt); 
      HMENU hmenu = CreatePopupMenu(); 
      InsertMenu(hmenu, 0, MF_BYPOSITION | MF_STRING, IDM_EXIT, L"Exit"); 
      TrackPopupMenu(hmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_BOTTOMALIGN, pt.x, pt.y, 0, hWnd, NULL); 
     } 
     break; 
    } 

    } 

    return DefWindowProc(hWnd, uMsg, wParam, lParam); 
} 

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) 
{ 
    gInstance = hInstance; 
    WNDCLASSEX wx = { sizeof(WNDCLASSEX) }; 
    wx.lpfnWndProc = WndProc; 
    wx.hInstance = hInstance; 
    wx.lpszClassName = L"DNSChanger"; 
    RegisterClassEx(&wx); 

    CreateWindowEx(0, L"DNSChanger", L"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); 

    MSG msg; 
    while(GetMessage(&msg, NULL, 0, 0)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
    return 0; 
} 
+0

ありがとうございます!それはそれを修正し、私は今終了オプションがあり、ここから残りを終えることができるはずです! しかし、アイコンが消えてしまった...私は、タスクバーにシールドアイコンが表示される前に、空白になっていますが、どの変更が有効になったのかわかりません... – user3845041

+0

'MAKEINTRESOURCE(IDI_SHIELD)'も'IDI_SHIELD'が' 'WinUser.h" 'で' MAKEINTRESOURCE(32518) 'として定義されているため、以前のIDが間違っていると表示エラーの原因になっている可能性があります。アイコンキャッシュを消去するには、コンピュータを再起動する必要があります。あなたはとにかく自分のアイコンを供給したい。 –

+0

アイコンが消えた理由はわかりませんが、自分自身を追加した後は問題はありませんでした。プログラムが終了しました。助けてくれてありがとう。 デバッグからリリースに変わるということは、コンパイルするために、すべての文字列から先頭の 'L'を取り除かなければならないということでした。 – user3845041

関連する問題