Sends a message to the DetourIt tray icon.
void SendTrayMessage(
   UINT msg,
   WPARAM wParam,
   LPARAM lParam
type: UINT
            The message to send.
type: WPARAM
            A LPCSTR that contains the name of the item.
            This is also the identifier DetourIt will send back using WM_COPYDATA
type: LPARAM
            A CPipePacket containing the listener handle.
Return Value:
LRESULT, returns the menuID of the added item.
returns 0 if the function failed.
#include "Detourit.h"
#include "Detours.h"
#define IDB_OK        ((UINT)1)
HFONT g_hFont = 0;
INT_PTR CALLBACK DlgSettingsProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
    switch (message)
        case WM_COPYDATA:
            //pPipe will contain the converted data
            CPipePacket *pPipe = new CPipePacket;
            //Our message is contained in the LPARAM
            COPYDATASTRUCT *lpcds = (COPYDATASTRUCT *)lParam;
            std::vector<BYTE> message;
            //Copy data from the lpcds (the LPARAM) into the vector
            memcpy(&message.front(), lpcds->lpData, lpcds->cbData);
            //This will convert the message into a CPipePacket object
            BOOL ret = VectorToPipePacket(message, pPipe);
            if (ret == 1)
                //A check to see if the message is about our "Test Profile" window, if so then show it
                if (pPipe->ExtraInfo == "Test Profile")
                     ShowWindow(hwndDlg, SW_SHOW);
            delete pPipe;
            return TRUE;
        case WM_COMMAND:
            switch (LOWORD(wParam))
                 case IDB_OK:
                     ShowWindow(hwndDlg, SW_HIDE);
    return DefWindowProc(hwndDlg, message, wParam, lParam);
DWORD __stdcall InitThread(PVOID pData)
    //First of we register a Window Class for a dialog window.
    //When you make your own dialog, it should be done using a resource editor.
    //We set the WndProc to DlgSettingsProc, which is located above this code.
    WNDCLASSEX wcx = {sizeof(wcx)}; = CS_HREDRAW | CS_VREDRAW;                // redraw if size changes
    wcx.lpfnWndProc = (WNDPROC)DlgSettingsProc;         // points to window procedure
    wcx.cbClsExtra = 0;                                                  // no extra class memory
    wcx.cbWndExtra = 0;                                                // no extra window memory
    wcx.hInstance = (HINSTANCE)gModule;                     // handle to instance
    wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);        // predefined app. icon
    wcx.hCursor = LoadCursor(NULL, IDC_ARROW);         // predefined arrow
    wcx.hbrBackground = (HBRUSH)GRAY_BRUSH;          // gray background brush
    wcx.lpszClassName = L"ProfileClass";                        // name of window class
    ATOM theclass;
    theclass = RegisterClassEx(&wcx);
    //This will create a hidden window that we will use as a dialog
    HWND hProfileWindow = CreateWindowEx(WS_EX_APPWINDOW, L"ProfileClass", L"Test Profile", WS_TILEDWINDOW, 0, 0, 316, 183, NULL, NULL, (HINSTANCE)gModule, NULL);
    //A static control is used to display text in the window.
    //hBackground is a child to hProfileWindow
    HWND hBackground = CreateWindowEx(NULL, L"Static", L"\n  This is a test window used for testing \n  SendTrayMessage", WS_CHILD|WS_VISIBLE, 0, 0, 316, 183, hProfileWindow, NULL, (HINSTANCE)gModule, NULL);
    //A default push button with the text Ok.
    //hButton is a child to hProfileWindow
    HWND hButton = CreateWindowEx(NULL, L"BUTTON", L"Ok", WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON, 220, 105, 60, 25, hProfileWindow, (HMENU)IDB_OK, (HINSTANCE)gModule, NULL);
    //Arial, 16 p
    g_hFont = CreateFont(16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L"Arial");
    //This will replace the standard font with our own.
    SendMessage(hBackground, (UINT)WM_SETFONT, (WPARAM)g_hFont, NULL);
    SendMessage(hButton, (UINT)WM_SETFONT, (WPARAM)g_hFont, NULL);
    RECT rect;
    GetWindowRect(hProfileWindow, &rect);
    int width = rect.right - rect.left;
    int height = rect.bottom -;
    //This will place the dialog window in the middle of the screen
    SetWindowPos(hProfileWindow, NULL, GetSystemMetrics(SM_CXSCREEN) / 2 - (width / 2), GetSystemMetrics(SM_CYSCREEN) / 2 - (height / 2), 0, 0, SWP_NOSIZE);
    //The CPipePacket needs to contain the handle to the dialog (the listener).
    //This will make it able to recieve messages from DetourIt.
    CPipePacket *pSettings = new CPipePacket;
    pSettings->hListener = hProfileWindow;
    //DM_ADDMENU specifies that we want to add a menu to the tray.
    DWORD menuID = (DWORD_PTR)SendTrayMessage(DM_ADDMENU, (WPARAM)"Test Profile", (LPARAM)pSettings);
    //DM_ADDBREAK adds a break symbol so our menu item is separated from the others.
    DWORD breakID = (DWORD_PTR)SendTrayMessage(DM_ADDBREAK, (WPARAM)NULL, (LPARAM)pSettings);
    //pSettings needs to be deleted after it is used.
    delete pSettings;
    //A standard message loop
    MSG msg;
    BOOL bRet = 0;
    while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
        if (!IsWindow(hProfileWindow) || !IsDialogMessage(hProfileWindow, &msg))
     return 0; 
DWORD __stdcall AttachProfileExample(LPVOID pData)
    if ((DWORD)pData == 1)
        return (DWORD)CreateThread(NULL, 0, InitThread, pData, 0, NULL);
        return 0;
DWORD __stdcall DetachProfileExample(LPVOID pData)
    return 0;
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
    switch (ul_reason_for_call)
        case DLL_PROCESS_ATTACH:
            DetouritAttach(hModule, AttachProfileExample, TRUE); 
        case DLL_PROCESS_DETACH:
            DetouritDetach(DetachProfileExample, NULL);
    return TRUE;