commit 2d718e8ba5adc0e0fe0bfee62cbd08a9130aae2c Author: Quantum Date: Sat Mar 30 13:05:37 2013 -0400 Initial Commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..053bade --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.obj +*.exe +*.res +/build +/dist +/temp +/*.pdb diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5ce873e --- /dev/null +++ b/Makefile @@ -0,0 +1,64 @@ +SRCDIR=src +INCDIR=include + +CXX=cl /nologo +LD=link /nologo +CXXFLAGS=/c /I$(INCDIR) /W4 /Zi /DWIN32_LEAN_AND_MEAN /DWINVER=0x0501 /D_WIN32_WINNT=0x0501 /wd4100 /DUNICODE /D_UNICODE +LDFLAGS=/subsystem:windows /debug /manifest /incremental:no /opt:REF +LDFLAGS=$(LDFLAGS) "/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'" +RC=rc /nologo +RCFLAGS=/i$(INCDIR) +LIBS= + +!IFDEF DEBUG +BUILD=Debug +CXXFLAGS=$(CXXFLAGS) /DDEBUG +LDFLAGS=$(LDFLAGS) +!ELSE +BUILD=Release +LDFLAGS=$(LDFLAGS) +!ENDIF + +OUTDIR=build\$(BUILD) +DISTDIR=dist\$(BUILD) +FILES=$(OUTDIR)\Zalgo.obj \ + $(OUTDIR)\MainWindow.obj \ + $(OUTDIR)\Window.obj \ + $(OUTDIR)\DropTarget.obj \ + $(OUTDIR)\Converter.obj \ + $(OUTDIR)\PreviewWindow.obj \ + $(OUTDIR)\MyDropTarget.obj \ + $(OUTDIR)\Zalgo.res + +all: initdir $(DISTDIR)\Zalgo.exe + +initdir: + if not exist build md build + if not exist $(OUTDIR) md $(OUTDIR) + if not exist build md dist + if not exist $(DISTDIR) md $(DISTDIR) + +$(INCDIR)\MainWindow.hpp: $(INCDIR)\Window.hpp $(INCDIR)\MyDropTarget.hpp +$(INCDIR)\PreviewWindow.hpp: $(INCDIR)\Window.hpp +$(INCDIR)\MyDropTarget.hpp: $(INCDIR)\DropTarget.hpp + +$(SRCDIR)\MainWindow.cpp: $(INCDIR)\MainWindow.hpp $(INCDIR)\Converter.hpp $(INCDIR)\PreviewWindow.hpp +$(SRCDIR)\DropTarget.cpp: $(INCDIR)\DropTarget.hpp +$(SRCDIR)\MyDropTarget.cpp: $(INCDIR)\MyDropTarget.hpp +$(SRCDIR)\Zalgo.cpp: $(INCDIR)\MainWindow.hpp +$(SRCDIR)\PreviewWindow.cpp: $(INCDIR)\PreviewWindow.hpp +$(SRCDIR)\Converter.cpp: $(INCDIR)\Converter.hpp +$(SRCDIR)\Window.cpp: $(INCDIR)\Window.hpp + +$(OUTDIR)\Zalgo.res: Zalgo.rc + $(RC) $(RCFLAGS) /fo$@ $** + +{$(SRCDIR)}.cpp{$(OUTDIR)}.obj:: + $(CXX) $(CXXFLAGS) /Fo$(OUTDIR)\ /Fd$(OUTDIR)\ $< + +{$(SRCDIR)}.c{$(OUTDIR)}.obj:: + $(CXX) $(CXXFLAGS) /Fo$(OUTDIR)\ /Fd$(OUTDIR)\ $< + +$(DISTDIR)\Zalgo.exe: $(FILES) + $(LD) /out:$@ $(LDFLAGS) $** $(LIBS) + mt.exe -nologo -manifest $@.manifest -outputresource:$@;1 && del $@.manifest || set ERRORLEVEL=0 diff --git a/Zalgo.ico b/Zalgo.ico new file mode 100644 index 0000000..7cf4934 Binary files /dev/null and b/Zalgo.ico differ diff --git a/Zalgo.rc b/Zalgo.rc new file mode 100644 index 0000000..55fc490 --- /dev/null +++ b/Zalgo.rc @@ -0,0 +1,3 @@ +#include + +RID_ICON ICON Zalgo.ico diff --git a/include/Converter.hpp b/include/Converter.hpp new file mode 100644 index 0000000..2b00167 --- /dev/null +++ b/include/Converter.hpp @@ -0,0 +1,13 @@ +#pragma once +#ifndef id76AD7CF2_E519_495C_8C6B138352825E12 +#define id76AD7CF2_E519_495C_8C6B138352825E12 + +inline bool IsZalgo(wchar_t ch) +{ + return ch >= 0x0300 && ch < 0x0370 || ch == 0x489; +} + +wchar_t *ZalgoComes(const wchar_t *text, bool up, bool mid, bool down, int level); +wchar_t *ZalgoGoes(const wchar_t *zalgo); + +#endif diff --git a/include/DropTarget.hpp b/include/DropTarget.hpp new file mode 100644 index 0000000..0351269 --- /dev/null +++ b/include/DropTarget.hpp @@ -0,0 +1,38 @@ +#pragma once +#ifndef idC4123BF1_C7A2_4DF3_AEA77895CE6309D9 +#define idC4123BF1_C7A2_4DF3_AEA77895CE6309D9 + +#include +#include +#include + +class DropTarget : public IDropTarget { +public: + IFACEMETHODIMP QueryInterface(REFIID iid, void **ppv); + IFACEMETHODIMP_(ULONG) STDMETHODCALLTYPE AddRef(void); + IFACEMETHODIMP_(ULONG) STDMETHODCALLTYPE Release(void); + IFACEMETHODIMP DragOver(DWORD dwState, POINTL pt, + DWORD *pdwEffect); + IFACEMETHODIMP DragEnter(IDataObject *pDataObject, DWORD dwState, POINTL pt, + DWORD *pdwEffect); + IFACEMETHODIMP DragLeave(void); + IFACEMETHODIMP Drop(IDataObject *pDataObject, DWORD dwState, POINTL pt, + DWORD *pdwEffect); + + STDMETHODIMP_(BOOL) DragDropRegister(HWND hwnd, DWORD dwState=MK_LBUTTON); + + virtual DWORD OnDragEnter(POINTL point, DWORD effect, DWORD state, + IDataObject *data); + virtual DWORD OnDragOver(POINTL point, DWORD effect, DWORD state); + virtual void OnDragLeave(void) {} + virtual DWORD OnDrop(POINTL point, DWORD effect, DWORD state, + IDataObject *data) = 0; + +protected: + HWND m_hwnd; + DWORD m_state; +private: + volatile ULONG m_ref; +}; + +#endif diff --git a/include/MainWindow.hpp b/include/MainWindow.hpp new file mode 100644 index 0000000..3b593b8 --- /dev/null +++ b/include/MainWindow.hpp @@ -0,0 +1,37 @@ +#pragma once +#ifndef id68C60171_0140_4DE1_B7255EFF557A74F9 +#define id68C60171_0140_4DE1_B7255EFF557A74F9 + +#include +#include +#include + +#include +#include + +class MainWindow : public Window { +public: + virtual LPCTSTR ClassName() { return TEXT("Zalgo_Main"); } + static MainWindow *Create(LPCTSTR szTitle); +protected: + LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnCreate(); + LRESULT OnDestroy(); + void OnPaint(); + + virtual HICON GetIcon(); + + HWND m_message; + HWND m_goUp, m_goMiddle, m_goDown; + HWND m_messMini, m_messNormal, m_messMax, m_messCustom; + HWND m_messLevel, m_messUpDown; + HWND m_mess, m_unmess, m_previewShow; + MyDropTarget m_dropTarget; + PreviewWindow *m_preview; +private: + HFONT hFont, hFontMono; + HBRUSH hBrush; + UDACCEL *udaSecondAccel; +}; + +#endif // header diff --git a/include/MyDropTarget.hpp b/include/MyDropTarget.hpp new file mode 100644 index 0000000..c71bf49 --- /dev/null +++ b/include/MyDropTarget.hpp @@ -0,0 +1,17 @@ +#pragma once +#ifndef id8025A145_C3EF_4938_A70FBAFE9C2F9712 +#define id8025A145_C3EF_4938_A70FBAFE9C2F9712 + +#include + +#define WM_DROPTEXT (WM_USER+1) +#define WM_DROPFILE (WM_USER+2) + +class MyDropTarget : public DropTarget { + virtual DWORD OnDragEnter(POINTL point, DWORD effect, DWORD state, + IDataObject *data); + virtual DWORD OnDrop(POINTL point, DWORD effect, DWORD state, + IDataObject *data); +}; + +#endif diff --git a/include/PreviewWindow.hpp b/include/PreviewWindow.hpp new file mode 100644 index 0000000..e035f89 --- /dev/null +++ b/include/PreviewWindow.hpp @@ -0,0 +1,34 @@ +#pragma once +#ifndef id68C60174_0140_4DE1_B7255EFF557A74F9 +#define id68C60174_0140_4DE1_B7255EFF557A74F9 + +#include +#include + +#include +#include + +#define WM_CHANGETEXT (WM_USER+1) + +class PreviewWindow : public Window { +public: + virtual LPCTSTR ClassName() { return TEXT("Zalgo_Preview"); } + static PreviewWindow *Create(LPCTSTR szTitle); + void Destroy() { DestroyWindow(m_hwnd); } +protected: + LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT OnCreate(); + LRESULT OnDestroy(); + void OnPaint(); + + virtual HICON GetIcon(); +private: + HFONT hFont; + HBRUSH hBrush; + int xChar, yChar, xUpper, xClient, yClient, xClientMax, xPos, yPos; + LPTSTR *lpLines; + int lines; + bool empty; +}; + +#endif // header diff --git a/include/Window.hpp b/include/Window.hpp new file mode 100644 index 0000000..645b974 --- /dev/null +++ b/include/Window.hpp @@ -0,0 +1,62 @@ +#pragma once +#ifndef idC3714409_EABC_45DE_B5338EC60149AE87 +#define idC3714409_EABC_45DE_B5338EC60149AE87 + +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include + +inline void MakeRect(RECT &rect, int x, int y, int cx, int cy) +{ + rect.left = x; + rect.top = y; + rect.right = x + cx; + rect.bottom = y + cy; +} + +inline void MakeRectRight(RECT &rect, int x, int y, int cx, int cy) +{ + MakeRect(rect, x - cx, y, cx, cy); +} + +inline void MakeRectBottom(RECT &rect, int x, int y, int cx, int cy) +{ + MakeRect(rect, x, y - cy, cx, cy); +} + +inline void MakeRectBottomRight(RECT &rect, int x, int y, int cx, int cy) +{ + MakeRect(rect, x - cx, y - cy, cx, cy); +} + +class Window { +public: + HWND GetHWND() { return m_hwnd; } + static HINSTANCE GetInstance() { return (HINSTANCE) GetModuleHandle(NULL); } +protected: + virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual void PaintContent(PAINTSTRUCT *pps) {} + virtual LPCTSTR ClassName() = 0; + virtual HICON GetIcon() { return NULL; } + virtual BOOL WinRegisterClass(WNDCLASS *pwc) { + return RegisterClass(pwc); + } + virtual ~Window(); + + HWND WinCreateWindow(DWORD dwExStyle, LPCTSTR pszName, + DWORD dwStyle, int x, int y, int cx, + int cy, HWND hwndParent, HMENU hmenu); +private: + virtual void Register(); + void OnPaint(); + void OnPrintClient(HDC hdc); + + static LRESULT CALLBACK + s_WndProc(HWND hwnd, UINT uMsg, + WPARAM wParam, LPARAM lParam); +protected: + HWND m_hwnd; +}; + +#endif // header diff --git a/include/resource.h b/include/resource.h new file mode 100644 index 0000000..4501386 --- /dev/null +++ b/include/resource.h @@ -0,0 +1 @@ +#define RID_ICON 1 diff --git a/src/Converter.cpp b/src/Converter.cpp new file mode 100644 index 0000000..0f02e38 --- /dev/null +++ b/src/Converter.cpp @@ -0,0 +1,86 @@ +#include +#include +#include + +#include + +typedef std::basic_string wstring; + +const wchar_t zalgo_up_[] = { + 0x030d, 0x030e, 0x0304, 0x0305, 0x033f, 0x0311, 0x0306, 0x0310, 0x0352, + 0x0357, 0x0351, 0x0307, 0x0308, 0x030a, 0x0342, 0x0343, 0x0344, 0x034a, + 0x034b, 0x034c, 0x0303, 0x0302, 0x030c, 0x0350, 0x0300, 0x0301, 0x030b, + 0x030f, 0x0312, 0x0313, 0x0314, 0x033d, 0x0309, 0x0363, 0x0364, 0x0365, + 0x0366, 0x0367, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, + 0x036f, 0x033e, 0x035b, 0x0346, 0x031a, 0 +}; + +const wchar_t zalgo_down_[] = { + 0x0316, 0x0317, 0x0318, 0x0319, 0x031c, 0x031d, 0x031e, 0x031f, 0x0320, + 0x0324, 0x0325, 0x0326, 0x0329, 0x032a, 0x032b, 0x032c, 0x032d, 0x032e, + 0x032f, 0x0330, 0x0331, 0x0332, 0x0333, 0x0339, 0x033a, 0x033b, 0x033c, + 0x0345, 0x0347, 0x0348, 0x0349, 0x034d, 0x034e, 0x0353, 0x0354, 0x0355, + 0x0356, 0x0359, 0x035a, 0x0323, 0 +}; + +const wchar_t zalgo_mid_[] = { + 0x0315, 0x031b, 0x0340, 0x0341, 0x0358, 0x0321, 0x0322, 0x0327, 0x0328, + 0x0334, 0x0335, 0x0336, 0x034f, 0x035c, 0x035d, 0x035e, 0x035f, 0x0360, + 0x0362, 0x0338, 0x0337, 0x0361, 0x0489, 0 +}; + +const wstring zalgo_up = zalgo_up_; +const wstring zalgo_down = zalgo_down_; +const wstring zalgo_mid = zalgo_mid_; + +inline int randint(int min, int max) +{ + if (min == max) + return min; + if (min >= max) + return 0; + return min + rand() % (max - min); +} + +inline wchar_t randchar(const wstring &str) +{ + return str[rand() % str.length()]; +} + +wchar_t *ZalgoComes(const wchar_t *text, bool up, bool mid, bool down, int level) +{ + wstring zalgo; + for (; *text; ++text) { + if (IsZalgo(*text)) + continue; + zalgo.push_back(*text); + if (*text < L' ') + continue; + int count_up = randint(level / 3, level), + count_mid = randint(level / 6, level / 2), + count_down = randint(level / 3, level); +#define IMPLEMENT_ZALGO(type) \ + if (type) {\ + for (int i = 0; i < count_##type; ++i) \ + zalgo.push_back(randchar(zalgo_##type)); \ + } + IMPLEMENT_ZALGO(up); + IMPLEMENT_ZALGO(mid); + IMPLEMENT_ZALGO(down); + } + wchar_t *out = new wchar_t[zalgo.length() + 1]; + StringCchCopy(out, zalgo.length() + 1, zalgo.c_str()); + return out; +} + +wchar_t *ZalgoGoes(const wchar_t *zalgo) +{ + wstring text; + for (; *zalgo; ++zalgo) + if (!IsZalgo(*zalgo)) + text += *zalgo; + wchar_t *out = new wchar_t[text.length() + 1]; + StringCchCopy(out, text.length() + 1, text.c_str()); + return out; + +} diff --git a/src/DropTarget.cpp b/src/DropTarget.cpp new file mode 100644 index 0000000..0308d1c --- /dev/null +++ b/src/DropTarget.cpp @@ -0,0 +1,91 @@ +#include + +HRESULT DropTarget::QueryInterface(REFIID iid, void **ppv) +{ + if (iid == IID_IUnknown) + *ppv = static_cast(this); + else if (iid == IID_IDropTarget) + *ppv = static_cast(this); + else { + *ppv = NULL; + return E_NOINTERFACE; + } + this->AddRef(); + return S_OK; +} + +ULONG DropTarget::AddRef(void) +{ + return InterlockedIncrement(&m_ref); +} + +ULONG DropTarget::Release(void) +{ + ULONG ref = InterlockedDecrement(&m_ref); + if (ref == 0) + delete this; + return ref; +} + +BOOL DropTarget::DragDropRegister(HWND hwnd, DWORD dwState) +{ + m_hwnd = hwnd; + m_state = dwState; + return SUCCEEDED(RegisterDragDrop(hwnd, this)); +} + +HRESULT DropTarget::DragEnter(IDataObject *pDataObject, DWORD dwState, + POINTL pt, DWORD *pdwEffect) +{ + if (pdwEffect == NULL) + return E_INVALIDARG; // Thank you for trying to crash me + + if (dwState != m_state) { + *pdwEffect = DROPEFFECT_NONE; + return S_OK; + } + + *pdwEffect = OnDragEnter(pt, *pdwEffect, dwState, pDataObject); + return S_OK; +} + +HRESULT DropTarget::DragOver(DWORD dwState, POINTL pt, DWORD *pdwEffect) +{ + if (pdwEffect == NULL) + return E_INVALIDARG; // Thank you for trying to crash me + + if (dwState != m_state) { + *pdwEffect = DROPEFFECT_NONE; + return S_OK; + } + + *pdwEffect = OnDragOver(pt, *pdwEffect, dwState); + return S_OK; +} + +HRESULT DropTarget::DragLeave(void) +{ + OnDragLeave(); + return S_OK; +} + +HRESULT DropTarget::Drop(IDataObject *pDataObject, DWORD dwState, POINTL pt, + DWORD *pdwEffect) +{ + if (pdwEffect == NULL) + return E_INVALIDARG; // Thank you for trying to crash me + + *pdwEffect = OnDrop(pt, *pdwEffect, dwState, pDataObject); + return S_OK; +} + +DWORD DropTarget::OnDragEnter(POINTL point, DWORD effect, DWORD state, + IDataObject *data) +{ + return DROPEFFECT_COPY; +} + +DWORD DropTarget::OnDragOver(POINTL point, DWORD effect, DWORD state) +{ + return effect; +} diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp new file mode 100644 index 0000000..321e80c --- /dev/null +++ b/src/MainWindow.cpp @@ -0,0 +1,382 @@ +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define BGCOLOUR RGB(0xF0, 0xF0, 0xF0) +#define LEFT(x, y, cx, cy) x, y, cx, cy +#define RIGHT(x, y, cx, cy) (x - cx), y, cx, cy +#define BOTTOM(x, y, cx, cy) x, (y - cy), cx, cy +#define BOTTOMRIGHT(x, y, cx, cy) (x - cx), (y - cy), cx, cy +#define ZALGO_GO_UP 0xAB01 +#define ZALGO_GO_CENTER 0xAB02 +#define ZALGO_GO_DOWN 0xAB03 +#define ZALGO_MINI_MESS 0xDEAD +#define ZALGO_NORMAL_MESS 0xDEAE +#define ZALGO_MAX_MESS 0xDEAF +#define ZALGO_CUSTOM_MESS 0xDEAC +#define ZALGO_MESS_LEVEL 0xDEAB +#define ZALGO_HE_COMES 0xBEEF +#define ZALGO_HE_GOES 0xBEEE +#define ZALGO_PREVIEW 0xBEED +#define ZALGO_MESSAGE 0xDEED + +#define ZALGO_INITIAL (L"To invoke the hive-mind representing chaos.\r\n"\ + L"Invoking the feeling of chaos.\r\n"\ + L"With out order.\r\n"\ + L"The Nezperdian hive-mind of chaos. Zalgo.\r\n"\ + L"He who Waits Behind The Wall.\r\n"\ + L"ZALGO!\r\n\r\n"\ + L"WARNING: Resulting text size is roughly original "\ + L"* (1 + fuck up level). Thou hast been warned.\r\n"\ + L"\r\n"\ + L"NOTE: If this program crashes on thee, blame "\ + L"thyself for fucking up a piece of text that is too "\ + L"big with a very high fuck up level.\r\n\r\n"\ + L"Do blame Windows for not able to show proper text "\ + L"in the edit control, for now, use the preview "\ + L"button.\r\n\r\n"\ + L"Bonus Geek Info: NFD text will lose all "\ + L"diacritics. Thou hast been warned.\r\n") + +UINT ZALGO_MESS_LEVEL_[3] = {6, 10, 14}; +#define ZALGO_MESS_LEVEL_OF(type) (ZALGO_MESS_LEVEL_[type-0xDEAD]) + +#ifndef FNERR_INVALIDFILENAME +# define FNERR_INVALIDFILENAME 0x3002 +#endif + +#pragma comment(lib, "shlwapi.lib") +#pragma comment(lib, "shell32.lib") +#pragma comment(lib, "comctl32.lib") +#pragma comment(lib, "comdlg32.lib") + +WNDPROC wpOrigEditProc; + +LRESULT APIENTRY EditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_KEYDOWN) { + if (wParam == L'A' && GetKeyState(VK_CONTROL) < 0) { + Edit_SetSel(hwnd, 0, -1); + return 0; + } + } + return CallWindowProc(wpOrigEditProc, hwnd, uMsg, + wParam, lParam); +} + +LRESULT MainWindow::OnCreate() +{ + NONCLIENTMETRICS ncmMetrics = { sizeof(NONCLIENTMETRICS) }; + RECT client; + + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncmMetrics, 0); + GetClientRect(m_hwnd, &client); + + hFont = CreateFontIndirect(&ncmMetrics.lfMessageFont); + hBrush = CreateSolidBrush(BGCOLOUR); + hFontMono = CreateFont(0, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, + OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + CLEARTYPE_QUALITY, FF_MODERN, TEXT("Consolas")); + + // Children + m_message = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, + ZALGO_INITIAL, WS_CHILDWINDOW | WS_VISIBLE | ES_LEFT | + ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL, + 0, 0, 0, 0, m_hwnd, (HMENU) ZALGO_MESSAGE, GetInstance(), NULL); + + m_goUp = CreateWindow(WC_BUTTON, L"fuck up going &up", + WS_CHILDWINDOW | WS_VISIBLE | BS_CHECKBOX, 0, 0, 0, 0, + m_hwnd, (HMENU) ZALGO_GO_UP, GetInstance(), NULL); + m_goMiddle = CreateWindow(WC_BUTTON, L"fuck up the &middle", + WS_CHILDWINDOW | WS_VISIBLE | BS_CHECKBOX, 0, 0, 0, 0, + m_hwnd, (HMENU) ZALGO_GO_CENTER, GetInstance(), NULL); + m_goDown = CreateWindow(WC_BUTTON, L"fuck up going &down", + WS_CHILDWINDOW | WS_VISIBLE | BS_CHECKBOX, 0, 0, 0, 0, + m_hwnd, (HMENU) ZALGO_GO_DOWN, GetInstance(), NULL); + + m_messMini = CreateWindow(WC_BUTTON, L"m&ini fuck up", + WS_CHILDWINDOW | WS_VISIBLE | BS_RADIOBUTTON, 0, 0, 0, 0, + m_hwnd, (HMENU) ZALGO_MINI_MESS, GetInstance(), NULL); + m_messNormal = CreateWindow(WC_BUTTON, L"&normal fuck up", + WS_CHILDWINDOW | WS_VISIBLE | BS_RADIOBUTTON, 0, 0, 0, 0, + m_hwnd, (HMENU) ZALGO_NORMAL_MESS, GetInstance(), NULL); + m_messMax = CreateWindow(WC_BUTTON, L"m&axi fuck up", + WS_CHILDWINDOW | WS_VISIBLE | BS_RADIOBUTTON, 0, 0, 0, 0, + m_hwnd, (HMENU) ZALGO_MAX_MESS, GetInstance(), NULL); + m_messCustom = CreateWindow(WC_BUTTON, L"c&ustom fuck up", + WS_CHILDWINDOW | WS_VISIBLE | BS_RADIOBUTTON, 0, 0, 0, 0, + m_hwnd, (HMENU) ZALGO_CUSTOM_MESS, GetInstance(), NULL); + + m_messLevel = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, NULL, + WS_CHILDWINDOW | WS_VISIBLE | ES_NUMBER | ES_LEFT | ES_READONLY, + 0, 0, 0, 0, m_hwnd, (HMENU) ZALGO_MESS_LEVEL, GetInstance(), NULL); + m_messUpDown = CreateWindow(UPDOWN_CLASS, NULL, + WS_CHILDWINDOW | WS_VISIBLE | UDS_AUTOBUDDY | UDS_SETBUDDYINT | + UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_HOTTRACK, + 0, 0, 0, 0, m_hwnd, NULL, GetInstance(), NULL); + + m_mess = CreateWindow(WC_BUTTON, L"HE &COMES!!!", + WS_CHILDWINDOW | WS_VISIBLE | BS_DEFPUSHBUTTON, 0, 0, 0, 0, + m_hwnd, (HMENU) ZALGO_HE_COMES, GetInstance(), NULL); + m_unmess = CreateWindow(WC_BUTTON, L"HE &GOES!!!", + WS_CHILDWINDOW | WS_VISIBLE | BS_PUSHBUTTON, 0, 0, 0, 0, + m_hwnd, (HMENU) ZALGO_HE_GOES, GetInstance(), NULL); + m_previewShow = CreateWindow(WC_BUTTON, L"&Preview", + WS_CHILDWINDOW | WS_VISIBLE | BS_PUSHBUTTON, 0, 0, 0, 0, + m_hwnd, (HMENU) ZALGO_PREVIEW, GetInstance(), NULL); + + PostMessage(m_messUpDown, UDM_SETRANGE32, 1, ZALGO_MESS_LEVEL_OF(ZALGO_MAX_MESS)); + PostMessage(m_messUpDown, UDM_SETPOS32, 0, ZALGO_MESS_LEVEL_OF(ZALGO_NORMAL_MESS)); +#define SETFONT(hwnd) PostMessage(hwnd, WM_SETFONT, (WPARAM) hFont, (LPARAM) FALSE) + SETFONT(m_message); + SETFONT(m_goUp); + SETFONT(m_goMiddle); + SETFONT(m_goDown); + SETFONT(m_messMini); + SETFONT(m_messNormal); + SETFONT(m_messMax); + SETFONT(m_messCustom); + SETFONT(m_messLevel); + SETFONT(m_mess); + SETFONT(m_unmess); + SETFONT(m_previewShow); +#undef SETFONT + + Button_SetCheck(m_goUp, 1); + Button_SetCheck(m_goMiddle, 1); + Button_SetCheck(m_goDown, 1); + Button_SetCheck(m_messNormal, 1); + Edit_Enable(m_messLevel, 0); + + if (!m_dropTarget.DragDropRegister(m_hwnd)) + MessageBox(m_hwnd, TEXT("Failed to register Drag and Drop handler"), + TEXT("Zalgo has COME!!!"), MB_ICONERROR); + + m_preview = PreviewWindow::Create(L"Text Preview"); + + // Subclassing + wpOrigEditProc = (WNDPROC) SetWindowLongPtr(m_message, + GWL_WNDPROC, (LONG_PTR) EditSubclassProc); + + return 0; +} + +LRESULT MainWindow::OnDestroy() +{ + SetWindowLongPtr(m_message, GWL_WNDPROC, (LONG_PTR) wpOrigEditProc); + + DestroyWindow(m_message); + DestroyWindow(m_goUp); + DestroyWindow(m_goMiddle); + DestroyWindow(m_goDown); + DestroyWindow(m_messMini); + DestroyWindow(m_messNormal); + DestroyWindow(m_messMax); + DestroyWindow(m_messCustom); + DestroyWindow(m_messLevel); + DestroyWindow(m_messUpDown); + DestroyWindow(m_mess); + DestroyWindow(m_unmess); + DestroyWindow(m_previewShow); + delete m_preview; + return 0; +} + +HICON MainWindow::GetIcon() +{ + return LoadIcon(GetInstance(), MAKEINTRESOURCE(RID_ICON)); +} + +void MainWindow::OnPaint() +{ + PAINTSTRUCT ps; + BeginPaint(m_hwnd, &ps); + PaintContent(&ps); + EndPaint(m_hwnd, &ps); +} + +LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_CREATE: + return OnCreate(); + case WM_DESTROY: + return OnDestroy(); + case WM_NCDESTROY: + PostQuitMessage(0); + break; + case WM_PAINT: + OnPaint(); + return 0; + case WM_SIZE: { + RECT client; + GetClientRect(m_hwnd, &client); +#define REPOS(hwnd, k) SetWindowPos(hwnd, 0, k, SWP_NOACTIVATE|SWP_NOZORDER) + REPOS(m_message, LEFT(12, 12, client.right - 24, client.bottom - 94)); + REPOS(m_goUp, BOTTOM(12, client.bottom - 59, 140, 20)); + REPOS(m_goMiddle, BOTTOM(12, client.bottom - 34, 140, 20)); + REPOS(m_goDown, BOTTOM(12, client.bottom - 9, 140, 20)); + REPOS(m_messMini, BOTTOM(160, client.bottom - 59, 120, 20)); + REPOS(m_messNormal, BOTTOM(160, client.bottom - 34, 120, 20)); + REPOS(m_messMax, BOTTOM(160, client.bottom - 9, 120, 20)); + REPOS(m_messCustom, BOTTOM(280, client.bottom - 59, 120, 20)); + REPOS(m_messLevel, BOTTOM(280, client.bottom - 34, 100, 20)); + REPOS(m_mess, BOTTOMRIGHT(client.right - 12, client.bottom - 41, 100, 25)); + REPOS(m_unmess, BOTTOMRIGHT(client.right - 12, client.bottom - 12, 100, 25)); + REPOS(m_previewShow,BOTTOMRIGHT(client.right - 117, client.bottom - 12, 100, 25)); +#undef REPOS + PostMessage(m_messUpDown, UDM_SETBUDDY, (WPARAM) m_messLevel, 0); + return 0; + } + case WM_COMMAND: + switch (HIWORD(wParam)) { + case BN_CLICKED: + switch (LOWORD(wParam)) { + case ZALGO_HE_COMES: + Button_Enable(m_mess, FALSE); + Button_Enable(m_unmess, FALSE); + + { + wchar_t *text; + int textlen; + wchar_t *zalgo; + + textlen = Edit_GetTextLength(m_message); + text = new wchar_t[textlen+1]; + Edit_GetText(m_message, text, textlen+1); + + zalgo = ZalgoComes(text, + IsDlgButtonChecked(m_hwnd, ZALGO_GO_UP), + IsDlgButtonChecked(m_hwnd, ZALGO_GO_CENTER), + IsDlgButtonChecked(m_hwnd, ZALGO_GO_DOWN), + GetDlgItemInt(m_hwnd, ZALGO_MESS_LEVEL, NULL, FALSE)); + + Edit_SetText(m_message, zalgo); + + delete [] zalgo; + delete [] text; + } + + Button_Enable(m_mess, TRUE); + Button_Enable(m_unmess, TRUE); + break; + case ZALGO_HE_GOES: + Button_Enable(m_mess, FALSE); + Button_Enable(m_unmess, FALSE); + + { + wchar_t *text; + int textlen; + wchar_t *zalgo; + + textlen = Edit_GetTextLength(m_message); + zalgo = new wchar_t[textlen+1]; + Edit_GetText(m_message, zalgo, textlen+1); + + text = ZalgoGoes(zalgo); + + Edit_SetText(m_message, text); + + delete [] text; + delete [] zalgo; + } + + Button_Enable(m_mess, TRUE); + Button_Enable(m_unmess, TRUE); + break; + case ZALGO_PREVIEW: { + wchar_t *text; + int textlen; + textlen = Edit_GetTextLength(m_message); + text = new wchar_t[textlen]; + Edit_GetText(m_message, text, textlen); + + SendMessage(m_preview->GetHWND(), WM_CHANGETEXT, 0, (LPARAM) text); + ShowWindow(m_preview->GetHWND(), SW_SHOW); + } + case ZALGO_GO_UP: + case ZALGO_GO_CENTER: + case ZALGO_GO_DOWN: + Button_SetCheck((HWND) lParam, !IsDlgButtonChecked(m_hwnd, LOWORD(wParam))); + break; + default: + Button_SetCheck(GetDlgItem(m_hwnd, ZALGO_MINI_MESS), 0); + Button_SetCheck(GetDlgItem(m_hwnd, ZALGO_NORMAL_MESS), 0); + Button_SetCheck(GetDlgItem(m_hwnd, ZALGO_MAX_MESS), 0); + Button_SetCheck(GetDlgItem(m_hwnd, ZALGO_CUSTOM_MESS), 0); + Button_SetCheck((HWND) lParam, 1); + + switch (LOWORD(wParam)) { + case ZALGO_MINI_MESS: + case ZALGO_NORMAL_MESS: + case ZALGO_MAX_MESS: + SetDlgItemInt(m_hwnd, ZALGO_MESS_LEVEL, + ZALGO_MESS_LEVEL_OF(LOWORD(wParam)), + FALSE); + Edit_Enable(m_messLevel, 0); + break; + case ZALGO_CUSTOM_MESS: + Edit_Enable(m_messLevel, 1); + } + } + break; + } + break; + case WM_CTLCOLORSTATIC: { + HBRUSH white = CreateSolidBrush(RGB(255, 255, 255)); + if ((HWND) lParam == m_messLevel && IsWindowEnabled(m_messLevel)) + return (LRESULT) white; + SetBkColor((HDC) wParam, BGCOLOUR); + return (LRESULT) hBrush; + } + case WM_KEYDOWN: + if (wParam == 'K' && GetKeyState(VK_CONTROL) < 0 && + GetKeyState(VK_SHIFT) < 0 && GetKeyState(VK_MENU) < 0) { + static bool unlocked = false; + // A user has tried to go beyond max, let is work + if (!unlocked && MessageBox(m_hwnd, L"\ +Thou hast tried to loosen my limits, dost thou promise that:\r\n\ + 1. thou will be responsible to use the string generated\r\n\ + 2. thou will be careful to not enter a number too large that will crash me\r\n\ + 3. if thou dost crash me, blame thyself for entering a number too large\r\n\ +\r\n\ +Dost thou agree?", L"About to Unlock Secret", MB_YESNO | MB_ICONQUESTION) == IDYES) { + PostMessage(m_messUpDown, UDM_SETRANGE32, 1, LONG_MAX); + PostMessage(m_messLevel, EM_SETREADONLY, 0, 0); + + unlocked = true; + } + return 0; + } + break; + case WM_DROPTEXT: + SendMessage(m_message, EM_REPLACESEL, 0, lParam); + return 0; + case WM_DROPFILE: + //SetWindowText(m_script, (LPTSTR) lParam); + return 0; + } + return __super::HandleMessage(uMsg, wParam, lParam); +} + +MainWindow *MainWindow::Create(LPCTSTR szTitle) +{ + MainWindow *self = new MainWindow(); + if (self && + self->WinCreateWindow(0, + szTitle, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, + NULL, NULL)) { + return self; + } + delete self; + return NULL; +} diff --git a/src/MyDropTarget.cpp b/src/MyDropTarget.cpp new file mode 100644 index 0000000..1a45029 --- /dev/null +++ b/src/MyDropTarget.cpp @@ -0,0 +1,66 @@ +#include +#include + +DWORD MyDropTarget::OnDragEnter(POINTL point, DWORD effect, DWORD state, + IDataObject *data) +{ + FORMATETC format = {CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + + if (SUCCEEDED(data->QueryGetData(&format))) + return DROPEFFECT_COPY; + + format.cfFormat = CF_HDROP; + if (SUCCEEDED(data->QueryGetData(&format))) + return DROPEFFECT_COPY; + return DROPEFFECT_NONE; +} + +DWORD MyDropTarget::OnDrop(POINTL point, DWORD effect, DWORD state, + IDataObject *data) +{ + FORMATETC format = {CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + STGMEDIUM medium; + +#ifdef UNICODE + format.cfFormat = CF_UNICODETEXT; +#endif + { + if (FAILED(data->GetData(&format, &medium))) + goto ansi; + LPTSTR str = (LPTSTR) GlobalLock(medium.hGlobal); + SendMessage(m_hwnd, WM_DROPTEXT, 0, (LPARAM) str); + GlobalUnlock(medium.hGlobal); + return DROPEFFECT_COPY; + } + + ansi: +#ifdef UNICODE + { + format.cfFormat = CF_TEXT; + if (FAILED(data->GetData(&format, &medium))) + goto hdrop; + LPSTR str = (LPSTR) GlobalLock(medium.hGlobal); + DWORD dwLen = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0) + 1; + LPWSTR wstr = new WCHAR[dwLen]; + MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, dwLen); + SendMessage(m_hwnd, WM_DROPTEXT, 0, (LPARAM) wstr); + delete [] wstr; + GlobalUnlock(medium.hGlobal); + return DROPEFFECT_COPY; + } +#endif + + hdrop: + { + format.cfFormat = CF_HDROP; + if (FAILED(data->GetData(&format, &medium))) + goto fail; + TCHAR file[MAX_PATH] = {0}; + DragQueryFile((HDROP) medium.hGlobal, 0, file, MAX_PATH); + SendMessage(m_hwnd, WM_DROPFILE, (WPARAM) medium.hGlobal, (LPARAM) file); + return DROPEFFECT_COPY; + } + + fail: + return DROPEFFECT_NONE; +} diff --git a/src/PreviewWindow.cpp b/src/PreviewWindow.cpp new file mode 100644 index 0000000..be65448 --- /dev/null +++ b/src/PreviewWindow.cpp @@ -0,0 +1,315 @@ +#include +#include + +#include +#include + +LRESULT PreviewWindow::OnCreate() +{ + NONCLIENTMETRICS ncmMetrics = { sizeof(NONCLIENTMETRICS) }; + RECT client; + + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncmMetrics, 0); + GetClientRect(m_hwnd, &client); + + hFont = CreateFontIndirect(&ncmMetrics.lfMessageFont); + + // Get the handle to the client area's device context. + HDC hdc = GetDC(m_hwnd); + TEXTMETRIC tm; + // Extract font dimensions from the text metrics. + GetTextMetrics(hdc, &tm); + xChar = tm.tmAveCharWidth; + xUpper =(tm.tmPitchAndFamily & 1 ? 3 : 2) * xChar/2; + yChar = tm.tmHeight + tm.tmExternalLeading; + // Free the device context. + ReleaseDC(m_hwnd, hdc); + // Set an arbitrary maximum width for client area. + //(xClientMax is the sum of the widths of 48 average + // lowercase letters and 12 uppercase letters.) + xClientMax = 48 * xChar + 12 * xUpper; + + lpLines = NULL; + return 0; +} + +LRESULT PreviewWindow::OnDestroy() +{ + return 0; +} + +HICON PreviewWindow::GetIcon() +{ + return LoadIcon(GetInstance(), MAKEINTRESOURCE(RID_ICON)); +} + +void PreviewWindow::OnPaint() +{ + PAINTSTRUCT ps; + SCROLLINFO si; + RECT rect; + + BeginPaint(m_hwnd, &ps); + GetClientRect(m_hwnd, &rect); + + if (empty) + goto done; + + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + GetScrollInfo(m_hwnd, SB_VERT, &si); + yPos = si.nPos; + + SelectObject(ps.hdc, hFont); + SetBkColor(ps.hdc, RGB(0xF0, 0xF0, 0xF0)); + // Find painting limits. + int FirstLine = max(0, yPos + ps.rcPaint.top / yChar); + int LastLine = min(lines - 1, yPos + ps.rcPaint.bottom / yChar); + + // Get horizontal scroll bar position. + GetScrollInfo(m_hwnd, SB_HORZ, &si); + xPos = si.nPos; + for (int i = FirstLine; i <= LastLine; i++) { + int x = xChar *(1 - xPos); + int y = yChar *(i - yPos); + rect.top = y; + rect.left = x; + DrawText(ps.hdc, lpLines[i], -1, &rect, DT_NOCLIP); + } + done: + EndPaint(m_hwnd, &ps); +} + +LRESULT PreviewWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) { + case WM_CREATE: + return OnCreate(); + case WM_DESTROY: + return OnDestroy(); + case WM_NCDESTROY: + PostQuitMessage(0); + break; + case WM_PAINT: + OnPaint(); + return 0; + case WM_SIZE: { + RECT client; + SCROLLINFO si; + + GetClientRect(m_hwnd, &client); + yClient = client.bottom - client.top; + xClient = client.right - client.left; + + // Set the vertical scrolling range and page size + si.cbSize = sizeof(si); + si.fMask = SIF_RANGE | SIF_PAGE; + si.nMin = 0; + si.nMax = lines - 1; + si.nPage = yClient / yChar; + SetScrollInfo(m_hwnd, SB_VERT, &si, TRUE); + + // Set the horizontal scrolling range and page size. + si.cbSize = sizeof(si); + si.fMask = SIF_RANGE | SIF_PAGE; + si.nMin = 0; + si.nMax = 2 + xClientMax / xChar; + si.nPage = xClient / xChar; + SetScrollInfo(m_hwnd, SB_HORZ, &si, TRUE); + return 0; + } + case WM_HSCROLL: { + SCROLLINFO si; + // Get all the vertial scroll bar information. + si.cbSize = sizeof(si); + si.fMask = SIF_ALL; + + // Save the position for comparison later on. + GetScrollInfo(m_hwnd, SB_HORZ, &si); + xPos = si.nPos; + switch(LOWORD(wParam)) { + // User clicked the left arrow. + case SB_LINELEFT: + si.nPos -= 1; + break; + // User clicked the right arrow. + case SB_LINERIGHT: + si.nPos += 1; + break; + // User clicked the scroll bar shaft left of the scroll box. + case SB_PAGELEFT: + si.nPos -= si.nPage; + break; + // User clicked the scroll bar shaft right of the scroll box. + case SB_PAGERIGHT: + si.nPos += si.nPage; + break; + // User dragged the scroll box. + case SB_THUMBTRACK: + si.nPos = si.nTrackPos; + break; + } + // Set the position and then retrieve it. Due to adjustments + // by Windows it may not be the same as the value set. + si.fMask = SIF_POS; + SetScrollInfo(m_hwnd, SB_HORZ, &si, TRUE); + GetScrollInfo(m_hwnd, SB_HORZ, &si); + + // If the position has changed, scroll the window. + if(si.nPos != xPos) + ScrollWindow(m_hwnd, xChar *(xPos - si.nPos), 0, NULL, NULL); + return 0; + } + case WM_VSCROLL: { + SCROLLINFO si; + // Get all the vertial scroll bar information. + si.cbSize = sizeof(si); + si.fMask = SIF_ALL; + GetScrollInfo(m_hwnd, SB_VERT, &si); + + // Save the position for comparison later on. + yPos = si.nPos; + switch(LOWORD(wParam)) { + // User clicked the HOME keyboard key. + case SB_TOP: + si.nPos = si.nMin; + break; + // User clicked the END keyboard key. + case SB_BOTTOM: + si.nPos = si.nMax; + break; + // User clicked the top arrow. + case SB_LINEUP: + si.nPos -= 1; + break; + // User clicked the bottom arrow. + case SB_LINEDOWN: + si.nPos += 1; + break; + // User clicked the scroll bar shaft above the scroll box. + case SB_PAGEUP: + si.nPos -= si.nPage; + break; + // User clicked the scroll bar shaft below the scroll box. + case SB_PAGEDOWN: + si.nPos += si.nPage; + break; + // User dragged the scroll box. + case SB_THUMBTRACK: + si.nPos = si.nTrackPos; + break; + } + // Set the position and then retrieve it. Due to adjustments + // by Windows it may not be the same as the value set. + si.fMask = SIF_POS; + SetScrollInfo(m_hwnd, SB_VERT, &si, TRUE); + GetScrollInfo(m_hwnd, SB_VERT, &si); + + // If the position has changed, scroll window and update it. + if(si.nPos != yPos) { + ScrollWindow(m_hwnd, 0, yChar *(yPos - si.nPos), NULL, NULL); + UpdateWindow(m_hwnd); + } + return 0; + } + case WM_MOUSEWHEEL: { + SCROLLINFO si; + // Get all the vertial scroll bar information. + si.cbSize = sizeof(si); + si.fMask = SIF_ALL; + GetScrollInfo(m_hwnd, SB_VERT, &si); + yPos = si.nPos; + + si.nPos -= GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA; + si.fMask = SIF_POS; + SetScrollInfo(m_hwnd, SB_VERT, &si, TRUE); + GetScrollInfo(m_hwnd, SB_VERT, &si); + + if(si.nPos != yPos) { + ScrollWindow(m_hwnd, 0, yChar *(yPos - si.nPos), NULL, NULL); + UpdateWindow(m_hwnd); + } + return 0; + } + case WM_CHANGETEXT: { + if (lpLines) { + for (int i = 0; i < lines; ++i) + delete [] lpLines[i]; + delete [] lpLines; + } + + LPTSTR str = (LPTSTR) lParam; + int l = 0, longest = 0, maxlen = 0; + + if (*str == L'\0') { + empty = true; + lpLines = NULL; + } else empty = false; + + while (*str++) + if (*str == L'\n') + ++l; + + if (*(str-1) != L'\n') + ++l; + + lines = l + 8; + lpLines = new LPTSTR[lines]; + for (int i = 0; i < 4; ++i) { + lpLines[i] = new TCHAR[1]; + lpLines[i][0] = L'\0'; + } + str = (LPTSTR) lParam; + for (int i = 0; i < l; ++i) { + LPTSTR start = str, end, buf; + int len; + while (*str++ != L'\n' && *(str-1) != L'\0'); + end = str - 1; + len = end - start; + if (len > maxlen) { + longest = i+4; + maxlen = len; + } + buf = new TCHAR[len + 1]; + memcpy(buf, start, len*sizeof(TCHAR)); + buf[len] = L'\0'; + lpLines[i+4] = buf; + } + for (int i = l + 4; i < lines; ++i) { + lpLines[i] = new TCHAR[1]; + lpLines[i][0] = L'\0'; + } + + int upper = 0, lower = 0; + for (LPTSTR i = lpLines[longest]; *i; ++i) { + if (isupper(*i)) + ++upper; + else if (!IsZalgo(*i)) + ++lower; + } + xClientMax = lower * xChar + upper * xUpper; + + PostMessage(m_hwnd, WM_SIZE, 0, 0); + return 0; + } + case WM_CLOSE: + ShowWindow(m_hwnd, SW_HIDE); + return 0; + } + + return __super::HandleMessage(uMsg, wParam, lParam); +} + +PreviewWindow *PreviewWindow::Create(LPCTSTR szTitle) +{ + PreviewWindow *self = new PreviewWindow(); + if(self && + self->WinCreateWindow(0, + szTitle, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, + NULL, NULL)) { + return self; + } + delete self; + return NULL; +} diff --git a/src/Window.cpp b/src/Window.cpp new file mode 100644 index 0000000..17815e5 --- /dev/null +++ b/src/Window.cpp @@ -0,0 +1,88 @@ +#include + +#pragma comment(lib, "user32.lib") +#pragma comment(lib, "gdi32.lib") + +HWND Window::WinCreateWindow(DWORD dwExStyle, LPCTSTR pszName, + DWORD dwStyle, int x, int y, int cx, + int cy, HWND hwndParent, HMENU hmenu) +{ + Register(); + return CreateWindowEx(dwExStyle, ClassName(), pszName, dwStyle, + x, y, cx, cy, hwndParent, hmenu, GetInstance(), + this); +} + +Window::~Window() {} + +void Window::Register() +{ + WNDCLASS wc; + wc.style = 0; + wc.lpfnWndProc = Window::s_WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetInstance(); + wc.hIcon = GetIcon(); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = CreateSolidBrush(RGB(0xF0, 0xF0, 0xF0)); + wc.lpszMenuName = NULL; + wc.lpszClassName = ClassName(); + + WinRegisterClass(&wc); +} + +LRESULT CALLBACK +Window::s_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + Window *self; + if (uMsg == WM_NCCREATE) { + LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lParam; + self = (Window *)(lpcs->lpCreateParams); + self->m_hwnd = hwnd; + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM) self); + } else { + self = (Window *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + } + if (self) { + return self->HandleMessage(uMsg, wParam, lParam); + } else { + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } +} + +LRESULT Window::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_NCDESTROY: { + LRESULT lres; + lres = DefWindowProc(m_hwnd, uMsg, wParam, lParam); + SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0); + delete this; + return lres; + } + case WM_PAINT: + OnPaint(); + return 0; + case WM_PRINTCLIENT: + OnPrintClient(reinterpret_cast(wParam)); + return 0; + } + return DefWindowProc(m_hwnd, uMsg, wParam, lParam); +} + +void Window::OnPaint() +{ + PAINTSTRUCT ps; + BeginPaint(m_hwnd, &ps); + PaintContent(&ps); + EndPaint(m_hwnd, &ps); +} + +void Window::OnPrintClient(HDC hdc) +{ + PAINTSTRUCT ps; + ps.hdc = hdc; + GetClientRect(m_hwnd, &ps.rcPaint); + PaintContent(&ps); +} diff --git a/src/Zalgo.cpp b/src/Zalgo.cpp new file mode 100644 index 0000000..0bfdd85 --- /dev/null +++ b/src/Zalgo.cpp @@ -0,0 +1,30 @@ +#include +#include +#include + +#pragma comment(lib, "comctl32.lib") +#pragma comment(lib, "ole32.lib") + +class COleInitialize { +public: + COleInitialize() : m_hr(OleInitialize(NULL)) { } + ~COleInitialize() { if (SUCCEEDED(m_hr)) OleUninitialize(); } + operator HRESULT() const { return m_hr; } + HRESULT m_hr; +}; + +int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { + COleInitialize oleInit; + InitCommonControls(); + + MainWindow *win = MainWindow::Create(L"Unicode Diacritic-Polluted Text Generator"); + if (win) { + ShowWindow(win->GetHWND(), nCmdShow); + MSG msg; + while (GetMessage(&msg, NULL, 0, 0) > 0) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + return 0; +}