Пишем просто конзолно приложение на чист WinAPI, Бележки на програмист

Ние пишем просто конзолно приложение на чист WinAPI

В последната публикация настроихме WinAPI среда за програмиране и дори написахме програма за показване на кутия за съобщения. Днес ще напишем просто конзолно приложение и ще научим как да правим някои прости операции върху низове и дори ще се докоснем до въпроса за управлението на паметта.

Четенето и писането се извършват с помощта на процедурите ReadConsole и WriteConsole, съответно:

Изглежда не е трудно, но как да получите манипулатор на входния (stdin) или изходния (stdout) поток? Процедурата GetStdHandle е предназначена за това:

Както може би се досещате, процедурата взема константа, която определя кой манипулатор искаме да получим и връща този манипулатор.

Процедурата GetCommandLine връща указател към низ, съдържащ името на текущата програма и нейните аргументи, а процедурата CommandLineToArgvW разделя този низ на аргументи, връщайки масив от указатели към тези аргументи (lpArgs) и броя на аргументите (записан в nArgs, указателят към който се предава като втори аргумент). Паметта, разпределена за lpArgs, се освобождава с помощта на процедурата LocalFree.

До този момент, разбира се, сте забелязали, че тук се използват доста странни типове (INT, HANDLE, LPWSTR, ...). По принцип тези типове са обикновени C-типове, преименувани с typedefs. Например, вместо INT, можете спокойно да напишете int, а вместо TCHAR - wchar_t. Що се отнася до използваната конвенция за именуване на променливи (nArgs, hStdin, lpCommandLine, ...), това е същата унгарска нотация. Идеята е да кодирате типа на променливата в нейното име. Например, ако името на променлива започва с h, sz, dw или lp, тогава нейният тип е съответно манипулатор, низ или двойна дума.или показалец. Подробности можете да намерите тук. Има аргументи както за, така и против унгарската нотация. По-нататък ще използваме тази конвенция и имената на типа неясно поради причината, че те се използват в MSDN и Visual Studio и също са вътрешен стандарт на Microsoft. С други думи, това е начинът, по който се пише в WinAPI и повечето от изходния код, който ще намерите, използва точно такива конвенции. Кои сме ние, че да нарушаваме традициите и да осъждаме нечия култура?

Нека да преминем от думи към дела и да напишем някаква програма:

#define STRLEN(x) (sizeof(x)/sizeof(TCHAR) - 1) const TCHAR szMsg [ ] = L "Как се казваш? \n" ;

void ChangeTextColor (HANDLE hSomeHandle) < INT nArgs = 0; LPWSTR lpCommandLine = GetCommandLine ( ) ; LPWSTR * lpArgs = CommandLineToArgvW (lpCommandLine, & nArgs); if (nArgs >= 2 && 0 == lstrcmpi (lpArgs [1], L "зелено")) < SetConsoleTextAttribute (hSomeHandle, FOREGROUND_GREEN); > LocalFree (lpArgs) ; >

int main() < HANDLE hStdout = GetStdHandle (STD_OUTPUT_HANDLE) ; HANDLE hStdin = GetStdHandle (STD_INPUT_HANDLE) ; TCHAR szName [16]; TCHAR szResp [32]; DWORD dwCount = 0;

wsprintf ( szResp , L "Здравей, %s! \n " , szName ); WriteConsole (hStdout, & szResp, lstrlen (szResp), & dwCount, NULL);

Разбира се, веднага разбрахте, че тази програма иска потребителско име и след това му казва „здравей“. Програмата също така проверява предадените аргументи и ако низът „green“ е предаден като първи аргумент (буквите могат да бъдат във всеки случай), тогава цветът на изходния текст се променя на зелен. Това се прави с помощта на процедурата SetConsoleTextAttribute. За сравнение на низовеизползва се процедурата lstrcmpi, която е пълен аналог на процедурата strcmpi. Има и WinAPI процедури lstrcmp, lstrcpy, lstrncpy, lstrcat, lstrncat, lstrlen и wsprintf. Последните две процедури се използват и в горната програма. Както може би се досещате, те са аналози на strlen и sprintf.

В общи линии това е всичко. Както миналия път, програмата се компилира лесно с MinGW и работи под Wine, но цветът на изходния текст не се променя. За домашна работа можете да опитате да коригирате програмата, така че да върне цвета на текста в предишното състояние, преди да излезе. Тук ще ви помогне процедурата GetConsoleScreenBufferInfo. И ако тази задача ви се струва твърде лесна, опитайте да преведете програмата на български. Имайте предвид, че тук трябва да работите много!

Както винаги, приветствам вашите въпроси и допълнения.