Skip to content

Commit

Permalink
initial release
Browse files Browse the repository at this point in the history
  • Loading branch information
valnoxy committed Jul 7, 2024
1 parent 4579f37 commit 39ab04a
Show file tree
Hide file tree
Showing 8 changed files with 546 additions and 1 deletion.
57 changes: 56 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,56 @@
# TypeIt
<div align="center">

<!-- PROJECT LOGO -->
<br />
<a href="https://github.com/valnoxy/typeit">
<img src="https://dl.exploitox.de/bucker/gh-banner-bucker-typeit.png" alt="TypeIt Banner">
</a>
<br />

[![Version][version-shield]][version-url]
[![Download Counter][downloads-shield]][downloads-url]
[![License][license-shield]][license-url]
</div>

[version-shield]: https://img.shields.io/github/v/release/valnoxy/typeit?color=9565F6
[version-url]: https://github.com/valnoxy/typeit/releases

[downloads-shield]: https://img.shields.io/github/downloads/valnoxy/typeit/total.svg?color=431D93
[downloads-url]: https://github.com/valnoxy/typeit/releases

[license-shield]: https://img.shields.io/github/license/valnoxy/typeit?color=9565F6
[license-url]: https://img.shields.io/github/license/valnoxy/typeit

<div align="center">
<h3 align="center">TypeIt</h3>
<p align="center">
<p>An app that simulates and types clipboard content.</p>
<a href="https://github.com/valnoxy/typeit/issues">Report Bug</a>
·
<a href="https://github.com/valnoxy/typeit/discussions/">Discussions</a>
<br />
<br />
🎉 Version 1.0.0 is out. Check out the release notes
<a href="https://github.com/valnoxy/typeit/releases">here</a>.
<br />
<br />
</p>
</div>

---

# 🚀Introduction
TypeIt is a small application for typing the clipboard using a hotkey. This can be useful for environments where CTRL-V is blocked.

# 🤸 Usage
Start TypeIt like any other application. At the bottom of the taskbar you will find a small icon where you can set whether ENTER should be pressed after pasting.

The clipboard is typed in with the hotkey ```CTRL-B```.

# 🧾 License
TIelevated is licensed under [GPL-3.0](https://github.com/valnoxy/TIelevated/blob/main/LICENSE).

<hr>
<h6 align="center">© 2018 - 2024 valnoxy. All Rights Reserved.
<br>
By Jonas Günner &lt;[email protected]&gt;</h6>
31 changes: 31 additions & 0 deletions TypeIt.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34616.47
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TypeIt", "TypeIt\TypeIt.vcxproj", "{F15CAC6B-2232-441F-B08F-05263EE15BCC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F15CAC6B-2232-441F-B08F-05263EE15BCC}.Debug|x64.ActiveCfg = Debug|x64
{F15CAC6B-2232-441F-B08F-05263EE15BCC}.Debug|x64.Build.0 = Debug|x64
{F15CAC6B-2232-441F-B08F-05263EE15BCC}.Debug|x86.ActiveCfg = Debug|Win32
{F15CAC6B-2232-441F-B08F-05263EE15BCC}.Debug|x86.Build.0 = Debug|Win32
{F15CAC6B-2232-441F-B08F-05263EE15BCC}.Release|x64.ActiveCfg = Release|x64
{F15CAC6B-2232-441F-B08F-05263EE15BCC}.Release|x64.Build.0 = Release|x64
{F15CAC6B-2232-441F-B08F-05263EE15BCC}.Release|x86.ActiveCfg = Release|Win32
{F15CAC6B-2232-441F-B08F-05263EE15BCC}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {198EE6B5-EA2C-46CD-BEF8-1A9CDAE5ECA1}
EndGlobalSection
EndGlobal
Binary file added TypeIt/Resource.rc
Binary file not shown.
262 changes: 262 additions & 0 deletions TypeIt/TypeIt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
#include <windows.h>
#include <shellapi.h>
#include <iostream>
#include <string>
#include <thread>

#include "resource.h"

#define WM_TRAYICON (WM_USER + 1)
#define ID_TRAY_EXIT 1001
#define ID_TRAY_OPTION1 1002
#define ID_TRAY_OPTION2 1003

HINSTANCE hInst;
NOTIFYICONDATA nid;
HWND hWnd;
bool pressEnter = true;

// Read stored registry value
bool ReadRegistry(const wchar_t* keyPath, const wchar_t* valueName) {
HKEY hKey;
DWORD dwType = REG_DWORD;
DWORD dwData = 0;
DWORD dwDataSize = sizeof(DWORD);

LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, keyPath, 0, KEY_READ, &hKey);
if (result == ERROR_SUCCESS) {
result = RegQueryValueEx(hKey, valueName, nullptr, &dwType, reinterpret_cast<BYTE*>(&dwData), &dwDataSize);
RegCloseKey(hKey);
}

return (result == ERROR_SUCCESS && dwData != 0); // Return true if value exists and is non-zero
}

// Write stored registry value
bool WriteRegistry(bool value) {
const wchar_t* keyPath = L"SOFTWARE\\valnoxy\\TypeIt";
const wchar_t* valueName = L"PressEnter";

HKEY hKey;
DWORD dwDisposition;

LONG result = RegCreateKeyEx(
HKEY_CURRENT_USER,
keyPath,
0,
nullptr,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
nullptr,
&hKey,
&dwDisposition
);

if (result != ERROR_SUCCESS) {
std::cerr << "Failed to create registry key." << '\n';
return false;
}

DWORD data = value ? 1 : 0;
result = RegSetValueEx(
hKey,
valueName,
0,
REG_DWORD,
reinterpret_cast<const BYTE*>(&data),
sizeof(DWORD)
);

RegCloseKey(hKey);

if (result != ERROR_SUCCESS) {
std::cerr << "Failed to set registry value." << '\n';
return false;
}

return true;
}

std::wstring GetClipboardText() {
if (!OpenClipboard(nullptr)) {
return L"";
}

HANDLE hData = GetClipboardData(CF_UNICODETEXT);
if (hData == nullptr) {
CloseClipboard();
return L"";
}

auto pwszText = static_cast<wchar_t*>(GlobalLock(hData));
if (pwszText == nullptr) {
CloseClipboard();
return L"";
}

std::wstring text(pwszText);
GlobalUnlock(hData);
CloseClipboard();
return text;
}

// Simulate Keyboard Input
void SimulateKeyboardInput(const std::wstring& text) {
for (wchar_t c : text) {
INPUT input = { 0 };
input.type = INPUT_KEYBOARD;

if (c == L'\n') {
input.ki.wVk = VK_RETURN;
input.ki.dwFlags = 0;
SendInput(1, &input, sizeof(INPUT));
input.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &input, sizeof(INPUT));
}
else {
input.ki.wVk = 0;
input.ki.wScan = c;
input.ki.dwFlags = KEYEVENTF_UNICODE;
SendInput(1, &input, sizeof(INPUT));
input.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
SendInput(1, &input, sizeof(INPUT));
}

// Workaround for preventing typing too fast
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}

// Press Enter if option is enabled
if (pressEnter)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
INPUT input = { 0 };
input.type = INPUT_KEYBOARD;
input.ki.wVk = VK_RETURN;
input.ki.dwFlags = 0;
SendInput(1, &input, sizeof(INPUT));
input.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &input, sizeof(INPUT));
}
}

// Tray Icon
void CreateTrayIcon(HWND hwnd) {
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hwnd;
nid.uID = 1;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uCallbackMessage = WM_TRAYICON;
nid.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON1));
wcscpy_s(nid.szTip, L"TypeIt");

Shell_NotifyIcon(NIM_ADD, &nid);
}

void ShowContextMenu(HWND hwnd) {
POINT pt;
GetCursorPos(&pt);
HMENU hMenu = CreatePopupMenu();
if (hMenu) {
// Option 1
UINT uCheck1 = (pressEnter) ? MF_CHECKED : MF_UNCHECKED;
InsertMenu(hMenu, -1, MF_BYPOSITION | MF_STRING | uCheck1, ID_TRAY_OPTION1, L"CTRL-V + ENTER");

// Option 2
UINT uCheck2 = (!pressEnter) ? MF_CHECKED : MF_UNCHECKED;
InsertMenu(hMenu, -1, MF_BYPOSITION | MF_STRING | uCheck2, ID_TRAY_OPTION2, L"CTRL-V");

InsertMenu(hMenu, -1, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr);
InsertMenu(hMenu, -1, MF_BYPOSITION, ID_TRAY_EXIT, L"Exit");

// Display context menu
SetForegroundWindow(hwnd);
TrackPopupMenu(hMenu, TPM_BOTTOMALIGN | TPM_LEFTALIGN, pt.x, pt.y, 0, hwnd, nullptr);
DestroyMenu(hMenu);
}
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_HOTKEY:
if (wParam == 1) {
std::wstring clipboardText = GetClipboardText();
SimulateKeyboardInput(clipboardText);
}
break;
case WM_TRAYICON:
if (lParam == WM_RBUTTONUP) {
ShowContextMenu(hwnd);
}
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case ID_TRAY_OPTION1:
pressEnter = true;
WriteRegistry(true);
break;
case ID_TRAY_OPTION2:
pressEnter = false;
WriteRegistry(false);
break;
case ID_TRAY_EXIT:
PostQuitMessage(0);
break;
default:
break;
}
break;
case WM_DESTROY:
Shell_NotifyIcon(NIM_DELETE, &nid);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}

// Entry Point
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) {
hInst = hInstance;
WNDCLASS wc = { 0 };

wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = L"TypeItClass";

RegisterClass(&wc);

pressEnter = ReadRegistry(L"SOFTWARE\\valnoxy\\TypeIt", L"PressEnter");

hWnd = CreateWindowEx(
0,
L"TypeItClass",
L"TypeIt",
0,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
nullptr,
nullptr,
hInstance,
nullptr
);

if (hWnd == nullptr) {
return 0;
}

if (!RegisterHotKey(hWnd, 1, MOD_CONTROL, 'B')) {
MessageBox(nullptr, L"Failed to register hotkey! Make sure that no other application is already using the CTRL-B hotkey.", L"Error", MB_OK | MB_ICONERROR);
return 0;
}
CreateTrayIcon(hWnd);

MSG msg = { nullptr };
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

UnregisterHotKey(hWnd, 1);
return 0;
}
Loading

0 comments on commit 39ab04a

Please sign in to comment.