Skip to content

Commit

Permalink
Add files
Browse files Browse the repository at this point in the history
  • Loading branch information
yehwankim23 committed Jan 1, 2022
1 parent 091095e commit 206a37c
Show file tree
Hide file tree
Showing 15 changed files with 535 additions and 0 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# [RunCat](https://github.com/Kyome22/RunCat_for_windows) Clone

Program that displays an animation of a running cat on the taskbar

## Preview

CPU 0%

![Preview 1%](preview-0.gif)

CPU 100%

![Preview 100%](preview-100.gif)

## Usage

1. Download and unzip [RunCat Clone](https://github.com/yehwankim23/runcat-clone/releases/latest/download/runcat-clone.zip)
2. (Optional) Create a shortcut for `RunCat Clone.exe` and move it to the `Startup Folder` to run `RunCat Clone` on computer startup
3. Run `RunCat Clone.exe`
4. (Optional) Move the tray icon to the taskbar so that it is always displayed
Binary file added preview-0.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added preview-100.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions runcat-clone.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.8.34330.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "runcat-clone", "runcat-clone\runcat-clone.vcxproj", "{384F9E85-D3E1-47D2-A476-8BECD9081796}"
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
{384F9E85-D3E1-47D2-A476-8BECD9081796}.Debug|x64.ActiveCfg = Debug|x64
{384F9E85-D3E1-47D2-A476-8BECD9081796}.Debug|x64.Build.0 = Debug|x64
{384F9E85-D3E1-47D2-A476-8BECD9081796}.Debug|x86.ActiveCfg = Debug|Win32
{384F9E85-D3E1-47D2-A476-8BECD9081796}.Debug|x86.Build.0 = Debug|Win32
{384F9E85-D3E1-47D2-A476-8BECD9081796}.Release|x64.ActiveCfg = Release|x64
{384F9E85-D3E1-47D2-A476-8BECD9081796}.Release|x64.Build.0 = Release|x64
{384F9E85-D3E1-47D2-A476-8BECD9081796}.Release|x86.ActiveCfg = Release|Win32
{384F9E85-D3E1-47D2-A476-8BECD9081796}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8B874E24-8820-4BA9-90D7-DABBF6704BC2}
EndGlobalSection
EndGlobal
181 changes: 181 additions & 0 deletions runcat-clone/RunCatClone.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
#ifndef UNICODE
#define UNICODE
#endif

#include <Windows.h>
#include <strsafe.h>
#include <sstream>
#include <iomanip>

#include "resource.h"

const wchar_t szClass[] = L"RunCatCloneClass";
const wchar_t szTitle[] = L"RunCat Clone";

const UINT WM_APP_ANIMATE = WM_APP + 1;

HINSTANCE hInst;
NOTIFYICONDATA nid;

DWORD dwMilliseconds = 100;
std::wstringstream wss;

UINT64 previousIdleTime = 0;
UINT64 previousUsedTime = 0;
double previousPercent = 0;

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI wWinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nShowCmd
)
{
HANDLE hMutex = CreateMutex(NULL, FALSE, L"RunCatCloneMutex");

if (!hMutex || GetLastError() == ERROR_ALREADY_EXISTS)
{
MessageBox(NULL, L"RunCat Clone is already running.", szTitle, MB_ICONWARNING);
return 1;
}

hInst = hInstance;

WNDCLASS wc{};
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_APP));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szClass;

if (!RegisterClass(&wc))
{
MessageBox(NULL, L"Call to RegisterClass failed.", szTitle, MB_ICONWARNING);
return 1;
}

HWND hwnd = CreateWindow(
szClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInst,
NULL
);

if (!hwnd)
{
MessageBox(NULL, L"Call to CreateWindow failed.", szTitle, MB_ICONWARNING);
return 1;
}

ShowWindow(hwnd, SW_HIDE);
MSG msg;

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

ReleaseMutex(hMutex);
return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hwnd;
nid.uFlags = NIF_ICON | NIF_TIP | NIF_SHOWTIP;
nid.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_APP));
StringCchCopy(nid.szTip, ARRAYSIZE(nid.szTip), szTitle);
Shell_NotifyIcon(NIM_ADD, &nid);

nid.uVersion = NOTIFYICON_VERSION_4;
Shell_NotifyIcon(NIM_SETVERSION, &nid);

PostMessage(hwnd, WM_APP_ANIMATE, 0, 0);
return 0;
}
case WM_APP_ANIMATE:
{
nid.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_WHITE_CAT_0));
Shell_NotifyIcon(NIM_MODIFY, &nid);
Sleep(dwMilliseconds);

nid.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_WHITE_CAT_1));
Shell_NotifyIcon(NIM_MODIFY, &nid);
Sleep(dwMilliseconds);

nid.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_WHITE_CAT_2));
Shell_NotifyIcon(NIM_MODIFY, &nid);
Sleep(dwMilliseconds);

nid.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_WHITE_CAT_3));
Shell_NotifyIcon(NIM_MODIFY, &nid);
Sleep(dwMilliseconds);

nid.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_WHITE_CAT_4));
Shell_NotifyIcon(NIM_MODIFY, &nid);
Sleep(dwMilliseconds);

FILETIME idleTime, kernelTime, userTime;
double currentPercent = previousPercent;

if (GetSystemTimes(&idleTime, &kernelTime, &userTime))
{
UINT64 currentIdleTime
= (UINT64) idleTime.dwHighDateTime << 32 | (UINT64) idleTime.dwLowDateTime;
UINT64 currentUsedTime
= ((UINT64) kernelTime.dwHighDateTime << 32 | (UINT64) kernelTime.dwLowDateTime)
+ ((UINT64) userTime.dwHighDateTime << 32 | (UINT64) userTime.dwLowDateTime);

UINT64 idleTimeChange = currentIdleTime - previousIdleTime;
UINT64 usedTimeChange = currentUsedTime - previousUsedTime;

currentPercent = (usedTimeChange - idleTimeChange) * 100.0 / usedTimeChange;

previousIdleTime = currentIdleTime;
previousUsedTime = currentUsedTime;
}

previousPercent = (previousPercent + currentPercent) / 2;
dwMilliseconds = static_cast<DWORD>(2000 / (previousPercent + 20));

wss << std::fixed << std::setprecision(1) << currentPercent;
std::wstring wPercent(wss.str());
wss.str(L"");
wss.clear();
StringCchCopy(nid.szTip, ARRAYSIZE(nid.szTip), (wPercent + L"%").c_str());

PostMessage(hwnd, WM_APP_ANIMATE, 0, 0);
return 0;
}
case WM_DESTROY:
{
Shell_NotifyIcon(NIM_DELETE, &nid);
PostQuitMessage(0);
return 0;
}
default:
{
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
}
81 changes: 81 additions & 0 deletions runcat-clone/RunCatClone.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// Korean (Korea) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_KOR)
LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT
#pragma code_page(949)

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE
BEGIN
"resource.h\0"
END

2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END

3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END

#endif // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_APP ICON "resources\\app.ico"

IDI_WHITE_CAT_0 ICON "resources\\white_cat_0.ico"

IDI_WHITE_CAT_1 ICON "resources\\white_cat_1.ico"

IDI_WHITE_CAT_2 ICON "resources\\white_cat_2.ico"

IDI_WHITE_CAT_3 ICON "resources\\white_cat_3.ico"

IDI_WHITE_CAT_4 ICON "resources\\white_cat_4.ico"

#endif // Korean (Korea) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

21 changes: 21 additions & 0 deletions runcat-clone/resource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by RunCatClone.rc
//
#define IDI_APP 101
#define IDI_WHITE_CAT_0 102
#define IDI_WHITE_CAT_1 103
#define IDI_WHITE_CAT_2 104
#define IDI_WHITE_CAT_3 105
#define IDI_WHITE_CAT_4 106

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 107
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
Binary file added runcat-clone/resources/app.ico
Binary file not shown.
Binary file added runcat-clone/resources/white_cat_0.ico
Binary file not shown.
Binary file added runcat-clone/resources/white_cat_1.ico
Binary file not shown.
Binary file added runcat-clone/resources/white_cat_2.ico
Binary file not shown.
Binary file added runcat-clone/resources/white_cat_3.ico
Binary file not shown.
Binary file added runcat-clone/resources/white_cat_4.ico
Binary file not shown.
Loading

0 comments on commit 206a37c

Please sign in to comment.