コード例 #1
0
ファイル: SSDT.cpp プロジェクト: AmesianX/A-Protect
void CopySSDTDataToClipboard(HWND hWnd,CMyList *m_list)
{
	CString FunctionName;
	int ItemNum = m_list->GetItemCount();
	POSITION pos = m_list->GetFirstSelectedItemPosition(); //判断列表框中是否有选择项
	int Item = m_list->GetNextSelectedItem(pos); //将列表中被选择的下一项索引值保存到数组中

	FunctionName.Format(L"%s",m_list->GetItemText(Item,3));

	WCHAR lpwzFunctionName[260];

	memset(lpwzFunctionName,0,sizeof(lpwzFunctionName));
	wcscat_s(lpwzFunctionName,FunctionName);
	CHAR lpszFunctionName[1024];
	char *lpString = NULL;

	memset(lpwzFunctionName,0,sizeof(lpwzFunctionName));
	memset(lpszFunctionName,0,sizeof(lpszFunctionName));
	wcscat_s(lpwzFunctionName,FunctionName);
	WideCharToMultiByte( CP_ACP,
		0,
		lpwzFunctionName,
		-1,
		lpszFunctionName,
		wcslen(lpwzFunctionName)*2,
		NULL,
		NULL
		);
	lpString = setClipboardText(lpszFunctionName);
	if (lpString)
	{
		MessageBoxW(hWnd,L"操作成功!",L"A盾电脑防护",MB_ICONWARNING);
	}
}
コード例 #2
0
ファイル: main.cpp プロジェクト: johnwchadwick/pengsh
QString upload(PuushFile file) {
    QDateTime time = QDateTime::currentDateTime();
    QList<FormField> formData = {
        textField("k", settings.apiKey.toUtf8()),
        textField("z", "poop"),
        dataField("f", file.name, file.data)
    };

    QHttpMultiPart *form = createForm(formData);
    QNetworkReply *reply = apiCall("/api/up", form);

    if (!reply)
        return QString();

    QString replyText = QString::fromUtf8(reply->readAll());
    QStringList replyParts = replyText.split(',');

    if (replyParts.length() < 3) {
        if (!replyParts.isEmpty()) {
            if (replyParts.first() == "-2")
                trayicon->showMessage(QObject::tr("Upload error."), QObject::tr("Server rejected request."), QSystemTrayIcon::Critical);
            else if (replyParts.first() == "-1")
                trayicon->showMessage(QObject::tr("Upload error."), QObject::tr("Server error."), QSystemTrayIcon::Critical);
            else
                trayicon->showMessage(QObject::tr("Upload error."), QObject::tr("Unknown server error."), QSystemTrayIcon::Critical);
        } else {
            trayicon->showMessage(QObject::tr("Upload error."), QObject::tr("Empty response."), QSystemTrayIcon::Critical);
        }
        return QString();
    }

    recent.prepend({replyParts.at(2).toInt(), time, replyParts.at(1), file.name});
    setupMenu();

    QString url = replyParts.at(1);

    trayicon->showMessage(QObject::tr("Upload successful."), url, QSystemTrayIcon::Information, 5000);

    if (settings.onPuushActions & Settings::PlaySound)
        playSound("qrc:/notify.wav");
    if (settings.onPuushActions & Settings::CopyLink)
        setClipboardText(url);
    if (settings.onPuushActions & Settings::OpenInBrowser)
        QDesktopServices::openUrl(url);

    return url;
}
コード例 #3
0
/**
 * It will be called from JNext JavaScript side with passed string.
 * This method implements the interface for the JavaScript to native binding
 * for invoking native code. This method is triggered when JNext.invoke is
 * called on the JavaScript side with this native objects id.
 */
string JsClipboard::InvokeMethod(const std::string& command) {

	// Determine which function should be executed
	size_t splitter = command.find_first_of(" ");
	string strCommand = command.substr(0, splitter);

	if (strCommand == "setText") {
		if (command.length() > splitter) {
			string params = command.substr(splitter + 1, command.length());
			return convertLongToString(setClipboardText(params));
		} else {

		}
	} else if (strCommand == "getText") {
		return this->getTextFromClipboard();
	}
	return "Unsupported Method";

}
コード例 #4
0
ファイル: Process.cpp プロジェクト: AmesianX/A-Protect
void CopyProcessMD5ToClipboard(HWND hWnd,CMyList *m_list)
{
	CString ProcessPath;
	int ItemNum = m_list->GetItemCount();
	POSITION pos = m_list->GetFirstSelectedItemPosition(); //判断列表框中是否有选择项
	int Item = m_list->GetNextSelectedItem(pos); //将列表中被选择的下一项索引值保存到数组中

	ProcessPath.Format(L"%s",m_list->GetItemText(Item,3));

	WCHAR lpwzProcessPath[260];
	CHAR lpszProcessPath[1024];
	char *lpString = NULL;
	memset(lpwzProcessPath,0,sizeof(lpwzProcessPath));
	memset(lpszProcessPath,0,sizeof(lpszProcessPath));
	wcscat(lpwzProcessPath,ProcessPath);
	WideCharToMultiByte( CP_ACP,
		0,
		lpwzProcessPath,
		-1,
		lpszProcessPath,
		wcslen(lpwzProcessPath)*2,
		NULL,
		NULL
		);
	CHAR lpszNum[100] = {0};
	FILE * fp=fopen(lpszProcessPath,"rb");
	if(fp)
	{
		MD5VAL val;
		val = md5File(fp);
		wsprintfA(lpszNum,"%08x%08x%08x%08x",conv(val.a),conv(val.b),conv(val.c),conv(val.d));
		fclose(fp);
	}
	lpString = setClipboardText(lpszNum);
	if (lpString)
	{
		MessageBoxW(hWnd,L"操作成功!",L"A盾电脑防护",MB_ICONWARNING);
	}
}
コード例 #5
0
ファイル: system.cpp プロジェクト: smallbasic/SmallBASIC
void System::handleMenu(MAEvent &event) {
  int menuId = event.optionsBoxButtonIndex;
  int fontSize = _output->getFontSize();
  int menuItem = _systemMenu[menuId];
  delete [] _systemMenu;
  _systemMenu = NULL;

  switch (menuItem) {
  case MENU_SOURCE:
    showSystemScreen(true);
    break;
  case MENU_CONSOLE:
    showSystemScreen(false);
    break;
  case MENU_KEYPAD:
    maShowVirtualKeyboard();
    break;
  case MENU_RESTART:
    setRestart();
    break;
  case MENU_BACK:
    setBack();
    break;
  case MENU_ZOOM_UP:
    if (_fontScale > FONT_MIN) {
      _fontScale -= FONT_SCALE_INTERVAL;
      fontSize = (_initialFontSize * _fontScale / 100);
    }
    break;
  case MENU_ZOOM_DN:
    if (_fontScale < FONT_MAX) {
      _fontScale += FONT_SCALE_INTERVAL;
      fontSize = (_initialFontSize * _fontScale / 100);
    }
    break;
  case MENU_COPY:
  case MENU_CUT:
    if (get_focus_edit() != NULL) {
      char *text = get_focus_edit()->copy(menuItem == MENU_CUT);
      if (text) {
        setClipboardText(text);
        free(text);
        _output->redraw();
      }
    }
    break;
  case MENU_PASTE:
    if (get_focus_edit() != NULL) {
      char *text = getClipboardText();
      get_focus_edit()->paste(text);
      _output->redraw();
      free(text);
    }
    break;
  case MENU_SELECT_ALL:
    if (get_focus_edit() != NULL) {
      get_focus_edit()->selectAll();
      _output->redraw();
    }
    break;
  case MENU_CTRL_MODE:
    if (get_focus_edit() != NULL) {
      bool controlMode = get_focus_edit()->getControlMode();
      get_focus_edit()->setControlMode(!controlMode);
    }
    break;
  case MENU_EDITMODE:
    opt_ide = (opt_ide == IDE_NONE ? IDE_INTERNAL : IDE_NONE);
    break;
  case MENU_AUDIO:
    opt_mute_audio = !opt_mute_audio;
    break;
  case MENU_SCREENSHOT:
    ::screen_dump();
    break;
  case MENU_UNDO:
    event.type = EVENT_TYPE_KEY_PRESSED;
    event.key = SB_KEY_CTRL('z');
    break;
  case MENU_REDO:
    event.type = EVENT_TYPE_KEY_PRESSED;
    event.key = SB_KEY_CTRL('y');
    break;
  case MENU_SAVE:
    event.type = EVENT_TYPE_KEY_PRESSED;
    event.key = SB_KEY_CTRL('s');
    break;
  case MENU_RUN:
    event.type = EVENT_TYPE_KEY_PRESSED;
    event.key = SB_KEY_F(9);
    break;
  case MENU_DEBUG:
    event.type = EVENT_TYPE_KEY_PRESSED;
    event.key = SB_KEY_F(5);
    break;
  case MENU_OUTPUT:
    event.type = EVENT_TYPE_KEY_PRESSED;
    event.key = SB_KEY_CTRL('o');
    break;
  case MENU_HELP:
    event.type = EVENT_TYPE_KEY_PRESSED;
    event.key = SB_KEY_F(1);
    break;
  case MENU_SHORTCUT:
    if (!_activeFile.empty()) {
      addShortcut(_activeFile.c_str());
    }
    break;
  case MENU_SHARE:
    if (!_activeFile.empty()) {
      share(_activeFile.c_str());
    }
    break;
  case MENU_COMPLETION_0:
    completeKeyword(0);
    break;
  case MENU_COMPLETION_1:
    completeKeyword(1);
    break;
  case MENU_COMPLETION_2:
    completeKeyword(2);
    break;
  case MENU_COMPLETION_3:
    completeKeyword(3);
    break;
  }

  if (fontSize != _output->getFontSize()) {
    // restart the shell
    _output->setFontSize(fontSize);
    setRestart();
  }

  if (!isRunning()) {
    _output->flush(true);
  }
}
コード例 #6
0
bool executeCommand(const UINT cmd, const csWStringList& files)
{
  const csWString parallel  = regReadParallel();
  const DWORD parallelCount = regReadParallelCount();
  const bool    hasParallel = !parallel.empty()  &&  parallelCount > 1;

  const DWORD flags      = regReadFlags();
  const bool  isBatch    = testFlags(flags, CMD_FLAG_BATCH);
  const bool  isParallel = testFlags(flags, CMD_FLAG_PARALLEL)  &&  hasParallel;
  const bool  isUnc      = testFlags(flags, CMD_FLAG_UNC)  &&  cmd != Cmd_List;
  const bool  isUnix     = testFlags(flags, CMD_FLAG_UNIX);

  const csWString  scriptPath = regReadScriptsPath();
  const csWStringList scripts = regReadScripts();

  if(        cmd == Cmd_List                ||
             cmd == Cmd_ListWithPath        ||
             cmd == Cmd_ListWithPathTabular ) {
    int size = 0;
    for(csWStringList::const_iterator it = files.begin(); it != files.end(); it++) {
      wchar_t *uncName = 0;
      if( isUnc  &&  (uncName = resolveUNC(it->c_str())) != 0 ) {
        size += lenFN(csWString(uncName), cmd);
        delete[] uncName;
      } else {
        size += lenFN(*it, cmd);
      }
    }

    wchar_t *text = new wchar_t[size+1];
    if( text == 0 ) {
      return false;
    }

    int pos = 0;
    for(csWStringList::const_iterator it = files.begin(); it != files.end(); it++) {
      wchar_t *uncName = 0;
      if( isUnc  &&  (uncName = resolveUNC(it->c_str())) != 0 ) {
        catFN(text, pos, csWString(uncName), cmd);
        delete[] uncName;
      } else {
        catFN(text, pos, *it, cmd);
      }
    }
    text[size] = L'\0';

    if( files.size() == 1 ) {
      // Overwrite trailing <CR><LF>
      text[size-1] = text[size-2] = L'\0';
    }

    if( isUnix ) {
      replace(text, size, L'\\', L'/');
    }

    setClipboardText(text);
    delete[] text;

    return true;

  } else if( cmd == Cmd_CreateSymbolicLink ) {

    csWString symLink;

    IFileSaveDialog *saveDialog = NULL;
    HRESULT hr = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER,
                                  IID_IFileSaveDialog, (LPVOID*)&saveDialog);
    if( hr == S_OK ) {
      saveDialog->SetTitle(L"Create symbolic link");

      const int index = files.front().lastIndexOf(L'\\');
      if( index >= 0 ) {
        const csWString path = files.front().mid(0, index);
        const csWString name = files.front().mid(index+1);

        PIDLIST_ABSOLUTE pidl = NULL;
        SHParseDisplayName(path.c_str(), NULL, &pidl, 0, NULL);
        if( pidl != NULL ) {
          IShellItem *item = NULL;
          SHCreateItemFromIDList(pidl, IID_IShellItem, (LPVOID*)&item);
          if( item != NULL ) {
            saveDialog->SetFolder(item);
            item->Release();
          }
          CoTaskMemFree(pidl);
        }

        saveDialog->SetFileName(name.c_str());
      }

      const COMDLG_FILTERSPEC filterSpec = {
        L"All files", L"*.*"
      };
      saveDialog->SetFileTypes(1, &filterSpec);

      const FILEOPENDIALOGOPTIONS opts
          = FOS_OVERWRITEPROMPT
          | FOS_FORCEFILESYSTEM
          | FOS_PATHMUSTEXIST
          | FOS_CREATEPROMPT
          | FOS_NOREADONLYRETURN
          | FOS_NODEREFERENCELINKS
          | FOS_DONTADDTORECENT;
      saveDialog->SetOptions(opts);

      if( saveDialog->Show(NULL) == S_OK ) {
        IShellItem *item = NULL;
        if( saveDialog->GetResult(&item) == S_OK ) {
          wchar_t *filename = NULL;
          if( item->GetDisplayName(SIGDN_FILESYSPATH, &filename) == S_OK ) {
            symLink = filename;
            CoTaskMemFree(filename);
          }

          item->Release();
        }
      }

      saveDialog->Release();
    }

    if( !symLink.empty() ) {
      if( csFileExists(symLink.c_str()) ) {
        MessageBoxW(NULL, L"Symbolic link target already exists!",
                    L"Error", MB_OK | MB_ICONERROR);
        return false;
      }

      const DWORD linkFlags = csIsDirectory(files.front().c_str())
          ? SYMBOLIC_LINK_FLAG_DIRECTORY
          : 0;

      if( CreateSymbolicLinkW(symLink.c_str(),
                              files.front().c_str(),
                              linkFlags) == 0 ) {
        const DWORD lastError = GetLastError();

        csWString msg(L"ERROR(0x");
        msg += csWString::number(lastError, 16);
        msg += L"): ";
        msg += formatError(lastError);

        MessageBoxW(NULL, msg.c_str(),
                    L"Error", MB_OK | MB_ICONERROR);
        return false;
      }
    }

    return true;

  } else if( cmd == Cmd_CheckBatchProcessing ) {
    regWriteFlags(flags ^ CMD_FLAG_BATCH);
    return true;

  } else if( cmd == Cmd_CheckParallelExecution ) {
    regWriteFlags(flags ^ CMD_FLAG_PARALLEL);
    return true;

  } else if( cmd == Cmd_CheckResolveUncPaths ) {
    regWriteFlags(flags ^ CMD_FLAG_UNC);
    return true;

  } else if( cmd == Cmd_CheckUnixPathSeparators ) {
    regWriteFlags(flags ^ CMD_FLAG_UNIX);
    return true;

  } else if( Cmd_ExecuteScripts <= cmd  &&  cmd < Cmd_ExecuteScripts+scripts.size() ) {
    csWString script(scriptPath + L"\\");
    UINT i = 0;
    for(csWStringList::const_iterator it = scripts.begin(); it != scripts.end(); it++) {
      if( i == cmd-Cmd_ExecuteScripts ) {
        script += *it;
        break;
      }
      i++;
    }

    if( isParallel ) {
      csWStringList args(files);
      args.push_front(script);
      args.push_front(csWString::number(parallelCount));
      ShellExecuteW(NULL, L"open", parallel.c_str(), joinFileNames(args).c_str(),
                    NULL, SW_SHOWNORMAL);
    } else { // DO NOT use parallelizer
      if( isBatch ) {
        const csWString args = joinFileNames(files);
        ShellExecuteW(NULL, L"open", script.c_str(), args.c_str(), NULL, SW_SHOWNORMAL);
      } else { // NO batch processing
        for(csWStringList::const_iterator it = files.begin();
            it != files.end(); it++) {
          ShellExecuteW(NULL, L"open", script.c_str(), quoteFileName(*it).c_str(),
                        NULL, SW_SHOWNORMAL);
        }
      }
    }
    return true;

  }

  return false;
}
コード例 #7
0
ファイル: ClipWatcher.cpp プロジェクト: euske/clipwatcher
//  clipWatcherWndProc
//
static LRESULT CALLBACK clipWatcherWndProc(
    HWND hWnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam)
{
    //fwprintf(stderr, L"msg: %x, hWnd=%p, wParam=%p\n", uMsg, hWnd, wParam);

    switch (uMsg) {
    case WM_CREATE:
    {
        // Initialization.
        CREATESTRUCT* cs = (CREATESTRUCT*)lParam;
        ClipWatcher* watcher = (ClipWatcher*)(cs->lpCreateParams);
        if (watcher != NULL) {
            SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)watcher);
            if (logfp != NULL) {
                fwprintf(logfp, L"watcher: %s\n", watcher->name);
            }
            // Start watching the clipboard content.
            AddClipboardFormatListener(hWnd);
            SetTimer(hWnd, watcher->blink_timer_id, ICON_BLINK_INTERVAL, NULL);
            SetTimer(hWnd, watcher->check_timer_id, FILESYSTEM_INTERVAL, NULL);
            SendMessage(hWnd, WM_TASKBAR_CREATED, 0, 0);
        }
        return FALSE;
    }

    case WM_DESTROY:
    {
        // Clean up.
        LONG_PTR lp = GetWindowLongPtr(hWnd, GWLP_USERDATA);
        ClipWatcher* watcher = (ClipWatcher*)lp;
        if (watcher != NULL) {
            KillTimer(hWnd, watcher->blink_timer_id);
            KillTimer(hWnd, watcher->check_timer_id);
            // Stop watching the clipboard content.
            RemoveClipboardFormatListener(hWnd);
            // Unregister the icon.
            NOTIFYICONDATA nidata = {0};
            nidata.cbSize = sizeof(nidata);
            nidata.hWnd = hWnd;
            nidata.uID = watcher->icon_id;
            Shell_NotifyIcon(NIM_DELETE, &nidata);
        }
        PostQuitMessage(0);
        return FALSE;
    }

    case WM_CLIPBOARDUPDATE:
    {
        // Clipboard change detected.
        LONG_PTR lp = GetWindowLongPtr(hWnd, GWLP_USERDATA);
        ClipWatcher* watcher = (ClipWatcher*)lp;
        if (watcher != NULL) {
            DWORD seqno = GetClipboardSequenceNumber();
            if (watcher->seqno < seqno) {
                watcher->seqno = seqno;
                if (logfp != NULL) {
                    fwprintf(logfp, L"updated clipboard: seqno=%d\n", seqno);
                }
                for (int i = 0; i < CLIPBOARD_RETRY; i++) {
                    Sleep(CLIPBOARD_DELAY);
                    if (OpenClipboard(hWnd)) {
                        if (GetClipboardData(CF_ORIGIN) == NULL) {
                            WCHAR path[MAX_PATH];
                            StringCchPrintf(path, _countof(path), L"%s\\%s",
                                            watcher->dstdir, watcher->name);
                            exportClipFile(path);
                        }
                        WCHAR text[256];
                        int filetype = getClipboardText(text, _countof(text));
                        if (0 <= filetype) {
                            NOTIFYICONDATA nidata = {0};
                            nidata.cbSize = sizeof(nidata);
                            nidata.hWnd = hWnd;
                            nidata.uID = watcher->icon_id;
                            nidata.uFlags = NIF_INFO;
                            nidata.dwInfoFlags = NIIF_INFO;
                            nidata.uTimeout = 1;
                            StringCchCopy(nidata.szInfoTitle,
                                          _countof(nidata.szInfoTitle),
                                          MESSAGE_UPDATED);
                            StringCchCopy(nidata.szInfo,
                                          _countof(nidata.szInfo),
                                          text);
                            Shell_NotifyIcon(NIM_MODIFY, &nidata);
                            watcher->icon_blinking = HICON_FILETYPE[filetype];
                            watcher->icon_blink_count = ICON_BLINK_COUNT;
                        }
                        CloseClipboard();
                        break;
                    }
                }
            }
        }
        return FALSE;
    }

    case WM_NOTIFY_FILE:
    {
        // File change detected.
        LONG_PTR lp = GetWindowLongPtr(hWnd, GWLP_USERDATA);
        ClipWatcher* watcher = (ClipWatcher*)lp;
        if (watcher != NULL) {
            FileEntry* entry = checkFileChanges(watcher);
            if (entry != NULL) {
                if (logfp != NULL) {
                    fwprintf(logfp, L"updated file: path=%s\n", entry->path);
                }
                int index = rindex(entry->path, L'.');
                if (0 <= index) {
                    WCHAR* ext = &(entry->path[index]);
                    if (_wcsicmp(ext, FILE_EXT_TEXT) == 0) {
                        // CF_UNICODETEXT
                        int nchars;
                        LPWSTR text = readTextFile(entry->path, &nchars);
                        if (text != NULL) {
                            if (OpenClipboard(hWnd)) {
                                EmptyClipboard();
                                setClipboardOrigin(entry->path);
                                setClipboardText(text, nchars);
                                CloseClipboard();
                            }
                            free(text);
                        }
                    } else if (_wcsicmp(ext, FILE_EXT_BITMAP) == 0) {
                        // CF_DIB
                        BITMAPINFO* bmp = readBMPFile(entry->path);
                        if (bmp != NULL) {
                            if (OpenClipboard(hWnd)) {
                                EmptyClipboard();
                                setClipboardOrigin(entry->path);
                                setClipboardDIB(bmp);
                                CloseClipboard();
                            }
                            free(bmp);
                        }
                    }
                }
            }
        }
        return FALSE;
    }

    case WM_COMMAND:
    {
        // Command specified.
        LONG_PTR lp = GetWindowLongPtr(hWnd, GWLP_USERDATA);
        ClipWatcher* watcher = (ClipWatcher*)lp;
        switch (LOWORD(wParam)) {
        case IDM_OPEN:
            if (watcher != NULL) {
                if (OpenClipboard(hWnd)) {
                    openClipFile();
                    CloseClipboard();
                }
            }
            break;
        case IDM_EXIT:
            SendMessage(hWnd, WM_CLOSE, 0, 0);
            break;
        }
        return FALSE;
    }

    case WM_TIMECHANGE:
    {
        // Filesytem/Network share change detected.
        // NOTICE: We wanted to check if wParam is DBT_DEVICEARRIVAL.
        //   But it doesn't work when the system is suspended.
        LONG_PTR lp = GetWindowLongPtr(hWnd, GWLP_USERDATA);
        ClipWatcher* watcher = (ClipWatcher*)lp;
        if (watcher != NULL) {
            // Re-initialize the watcher object.
            StopClipWatcher(watcher);
        }
        return TRUE;
    }

    case WM_NOTIFY_ICON:
    {
        // UI event handling.
        POINT pt;
        HMENU menu = GetMenu(hWnd);
        if (menu != NULL) {
            menu = GetSubMenu(menu, 0);
        }
        switch (lParam) {
        case WM_LBUTTONDBLCLK:
            if (menu != NULL) {
                UINT item = GetMenuDefaultItem(menu, FALSE, 0);
                SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(item, 1), NULL);
            }
            break;
        case WM_LBUTTONUP:
            break;
        case WM_RBUTTONUP:
            if (GetCursorPos(&pt)) {
                SetForegroundWindow(hWnd);
                if (menu != NULL) {
                    TrackPopupMenu(menu, TPM_LEFTALIGN,
                                   pt.x, pt.y, 0, hWnd, NULL);
                }
                PostMessage(hWnd, WM_NULL, 0, 0);
            }
            break;
        }
        return FALSE;
    }

    case WM_TIMER:
    {
        LONG_PTR lp = GetWindowLongPtr(hWnd, GWLP_USERDATA);
        ClipWatcher* watcher = (ClipWatcher*)lp;
        if (watcher != NULL) {
            UINT_PTR timer_id = wParam;
            if (timer_id == watcher->blink_timer_id) {
                // Blink the icon.
                if (watcher->icon_blink_count) {
                    watcher->icon_blink_count--;
                    BOOL on = (watcher->icon_blink_count % 2);
                    NOTIFYICONDATA nidata = {0};
                    nidata.cbSize = sizeof(nidata);
                    nidata.hWnd = hWnd;
                    nidata.uID = watcher->icon_id;
                    nidata.uFlags = NIF_ICON;
                    nidata.hIcon = (on? watcher->icon_blinking : HICON_EMPTY);
                    Shell_NotifyIcon(NIM_MODIFY, &nidata);
                }
            } else if (timer_id == watcher->check_timer_id) {
                // Check the filesystem.
                StartClipWatcher(watcher);
            }
        }
        return FALSE;
    }

    case WM_CLOSE:
        DestroyWindow(hWnd);
        return FALSE;

    default:
        if (uMsg == WM_TASKBAR_CREATED) {
            LONG_PTR lp = GetWindowLongPtr(hWnd, GWLP_USERDATA);
            ClipWatcher* watcher = (ClipWatcher*)lp;
            if (watcher != NULL) {
                // Register the icon.
                NOTIFYICONDATA nidata = {0};
                nidata.cbSize = sizeof(nidata);
                nidata.hWnd = hWnd;
                nidata.uID = watcher->icon_id;
                nidata.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
                nidata.uCallbackMessage = WM_NOTIFY_ICON;
                nidata.hIcon = HICON_EMPTY;
                StringCchPrintf(nidata.szTip, _countof(nidata.szTip),
                                MESSAGE_WATCHING, watcher->srcdir);
                Shell_NotifyIcon(NIM_ADD, &nidata);
            }
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
}