Di waktu luang, saya bertanya pada diri saya kemungkinan membuat aplikasi dengan persyaratan berikut:
- setidaknya beberapa fungsi aplikasi yang berguna (yaitu, bukan tiruan)
- kehadiran antarmuka jendela
- ukuran kurang dari 1 Kb
Secara umum, standar aplikasi dengan ukuran hingga 1 Kb adalah 1k intro, yang merupakan jenis demoscene. Paling sering, ini adalah inisialisasi OpenGL yang ditulis dalam assembler, diikuti dengan memberi makan shader, yang melakukan pekerjaan utama (menggambar beberapa fraktal berwarna). Plus semua ini menuai oleh packer (misalnya crinkler).
Aplikasi ini secara harfiah dijilat ke byte, pengembangannya membutuhkan waktu berminggu-minggu bahkan berbulan-bulan.
Pendekatan ini terlalu keras, saya memutuskan untuk tidak melampaui pemrograman aplikasi yang biasa pada WinAPI.
Pada saat ini, penjualan musim panas dimulai di Steam, di mana orang dewasa diundang untuk mengibas alien dengan bijaksana dengan mouse di browser (ya, Valve lagi membuat game, seperti yang dijanjikan Gabe).
Ini menyinggung perasaan saya, dan saya memutuskan untuk mencoba menerapkan autoclicker paling sederhana dengan pengaturan minimal.
Diperlukan untuk dapat dalam 1 KB:
- pembuatan dan inisialisasi antarmuka
- fungsi jendela dengan penangan acara
- logika aplikasi utama (dibangun di atas fungsi GetAsyncKeyState dan SendInput)
Aplikasi ini akan dibuat dalam MSVC dalam C murni tanpa assembler dan SMS, dan kemudian dikompres dengan packer crinkler. Perlu dicatat bahwa crinkler memampatkan data (terutama yang dijernihkan) jauh lebih efisien daripada kode (sekitar dua kali). Karena itu, kami akan mencoba mentransfer fungsionalitas maksimal ke dalam data.
Dimulai dengan CreateWindow klasik untuk setiap elemen jendela, saya menyadari bahwa saya tidak dapat masuk ke dalam ukuran yang diperlukan.
Saya harus mencari alternatif. Dan dia menjadi fungsi CreateDialogIndirect, menciptakan dialog dari struktur DLGTEMPLATE yang diisi (terdiri dari heap DLGITEMTEMPLATE)
Untuk pembuatan dan pengisian struktur yang nyaman, saya memulai beberapa makro seperti ini:
#define NUMCHARS(p) (sizeof(p)/sizeof((p)[0])) #define DLGCTL(a) struct{DWORD style; DWORD exStyle; short x; short y; short cx; short cy; WORD id; WORD sysClass; WORD idClass; WCHAR wszTitle[NUMCHARS(a)]; WORD cbCreationData;} #define RADIO(x,y,cx,cy,id,title) {WS_VISIBLE|WS_CHILD|BS_RADIOBUTTON, 0, (x)/2, (y)/2,\n (cx)/2,(cy)/2, id, 0xFFFF, 0x0080, title, 0}
Sekarang Anda dapat mendeklarasikan dan mengisi struktur dengan elemen-elemen jendela masa depan:
static struct { DWORD style; DWORD dwExtendedStyle; WORD ccontrols; short x; short y; short cx; short cy; WORD menu; WORD windowClass; DLGCTL(LBL_BTN_LEFT) button_left; DLGCTL(LBL_BTN_MIDDLE) button_middle; DLGCTL(LBL_BTN_RIGHT) button_right; } Dlg = { WS_VISIBLE|WS_POPUP|WS_BORDER, 0, TOTAL_CONTROLS, 50/2, 50/2, WND_CX/2, WND_CY/2, 0, 0, RADIO(10, 0, 80, 30, IDC_BTN_LEFT, LBL_BTN_LEFT), RADIO(100, 0, 80, 30, IDC_BTN_MIDDLE, LBL_BTN_MIDDLE), RADIO(190, 0, 68, 30, IDC_BTN_RIGHT, LBL_BTN_RIGHT), };
Kami memberi makan struktur fungsi CreateDialogIndirect, dan inilah jendela yang dihasilkan:

Karena kami cocok dalam 1 kb, kami tidak memiliki manifes, seperti yang lainnya, dan karenanya tidak ada gaya visual juga. Semuanya abu-abu dan persegi, seperti di masa muda.
Tapi kami masih mengelak, menarik manifes dari shell32.dll dan menerapkan konteks berdasarkan itu ke aplikasi kami:
static ACTCTX actCtx = {sizeof(ACTCTX), ACTCTX_FLAG_RESOURCE_NAME_VALID|ACTCTX_FLAG_SET_PROCESS_DEFAULT|ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID, "shell32.dll", 0, 0, tmp, (LPCTSTR)124, 0, 0}; GetSystemDirectory(tmp,sizeof(tmp)); LoadLibrary("shell32.dll"); ActivateActCtx(CreateActCtx(&actCtx),(ULONG_PTR*)&tmp);
Sudah bergaya, modis:

Kami berhasil mengecilkan fungsi jendela menjadi lebih ringkas:
switch(msg) { case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_BTN_LEFT: case IDC_BTN_MIDDLE: case IDC_BTN_RIGHT: input[0].mi.dwFlags = wParam; input[1].mi.dwFlags = (wParam<<1); CheckRadioButton(hWnd,IDC_BTN_LEFT,IDC_BTN_MIDDLE,wParam); break; case IDC_BTN_HOLD: case IDC_BTN_TRIGGER: trigger_mode = (wParam==IDC_BTN_TRIGGER); CheckRadioButton(hWnd,IDC_BTN_HOLD,IDC_BTN_TRIGGER,wParam); break; case IDC_EDIT_PERIOD: period = GetDlgItemInt(hWnd,IDC_EDIT_PERIOD,(BOOL*)&tmp[0],0); break; case IDC_BTN_EXIT: exit(0); } break; } return DefWindowProc(hWnd,msg,wParam,lParam);
Dan kemudian saya berpikir bahwa akan lebih baik untuk menambahkan pemrosesan argumen baris perintah sehingga pengguna memiliki kesempatan untuk memulai dengan pengaturan yang diperlukan.
Sebagai contoh:
input.exe /L /T /P:20 /K:9 - 20 , / Tab
Pindahkan bagian dari fungsi di dalam data dan dapatkan sesuatu seperti:
static unsigned int arg_to_cmd[] = {IDC_BTN_HOLD, 0, 0, IDC_EDIT_KEY, IDC_BTN_LEFT, IDC_BTN_MIDDLE, 0, 0, IDC_EDIT_PERIOD, 0, IDC_BTN_RIGHT, 0, IDC_BTN_TRIGGER}; i = (char*)GetCommandLine(); while(*i) { if (*(i++)=='/')
Pawang keluar sangat kecil. Secara alami, tidak ada pemeriksaan dan perlindungan terhadap input yang salah, hanya minimum yang diperlukan.
Sekarang fungsi utama (saya taruh di aliran terpisah):
while(1) { key_state = (GetAsyncKeyState(key)>>1); if (trigger_mode) { if ((key_state)&&(key_state!=prev_key_state)) active^= 1; prev_key_state = key_state; } else active = key_state; if (active) SendInput(2,(LPINPUT)&input,sizeof(INPUT)); Sleep(period); }
Kami menekan objek-file yang dihasilkan crinkler'om - outputnya adalah 973 byte.
Dari jumlah tersebut, data menempati 163 byte (rasio kompresi 33,1%), kode - 517 byte (rasio kompresi 68,9%).
Dimungkinkan untuk menyusut dan lebih kuat (50 byte lainnya), tetapi tujuannya telah tercapai. Bahkan 51 byte cadangan tetap ada.
Persyaratan awal sepanjang jalan ditambahkan:
- memproses argumen baris perintah
- menampilkan jendela dengan gaya visual
Di beberapa tempat kode terlihat sangat bengkok. Ini karena saya menulisnya dengan bengkok. Dan di beberapa tempat ini memungkinkan untuk menghemat ruang.
Tentunya Anda dapat menemukan beberapa cara untuk mengurangi ukuran aplikasi, tetapi tidak secara dramatis (saya pikir byte adalah 50).
Hasil:
Sekarang Anda dapat memanggil alien dalam mode otomatis dengan kerusakan liar per detik.Dimungkinkan untuk membuat aplikasi ultra-kompak dengan fungsi bermanfaat yang sebenarnya digunakan dan antarmuka jendela.
Kebaruan:
Nol Saya mengumpulkan banyak teknik / perkembangan.
Kemanfaatan:
Tidak berguna, menyenangkan untuk.
Kode sumberBinerKritik, harapan, saran, kekaguman, kemarahan yang diterima.