Школа создателей компьютерных игр

BannerDrive.ru
[Главная] [С чего начать?] [Дистанционное обучение] [Статьи] [Обучалки] [Книги] [Софт] [Форум] [Ссылки] [О сайте]

Цветной текст



Подпишитесь на рассылку "Создание компьютерных игр"

Рассылки Subscribe.Ru
Создание компьютерных игр

Рассылка выходит раз в месяц.


Понравился сайт? Узнайте, как помочь сайту.


Рекомендуемые книги


Андре Ламот.
Программирование трехмерных игр для Windows. Советы профессионала по трехмерной графике и растеризации


Андре Ламот.
Программирование игр для Windows. Советы профессионала


Проголосуйте за сайт в рейтинге GameTop!
(нажмите на кнопку рейтинга)

GameTop - рейтинг игровых ресурсов. Портал Rolemancer (www.rolemancer.ru)

Не забывайте, что результаты рейтинга обновляются раз в неделю. Пожалуйста, голосуйте почаще!


Статистика посещаемости

Rambler's Top100

Контекст устройства | Все обучалки раздела | Ввод с клавиатуры

Описание

Объясняется, как рисовать цветной текст в окне. Также дается понятие об RGB.

Программа создает и выводит на экран окно, печатая по центру текст красным цветом.

Скачать обучалку (Visual C++ 6)

Работа программы

Исходный код


//            - "Talk to me like I'm a 3 year old!" Programming Lessons - 
//                                                                       
//            $Author:            Ben Humphrey      digiben@gametutorials.com    
//                                                                               
//            $Program:            Text                                          
//                                                                               
//            $Description:      Draw's "Hello World!" centered on the screen    
//                                                                               
//            $Date:                  7/20/00                                    
//                                                                               
// Перевод © 2004 Евгений Казеко
// www.gamecoder.kazeko.com
// evgeniy@kazeko.com

#include <windows.h>         
#include <stdio.h>           


RECT windowRect = {100, 100, 400, 400};      // (НОВОЕ)            

/*      Создадим прямоугольник, который определяет желаемое положение окна.
      Структура RECT работает вот так: {left, top, right, bottom}
      (лево, верх, право, низ)
      Помните, когда мы инициализируем переменную, мы можем заполнять
      таким образом структуру. Если мы не установим здесь значения
      переменных структуры, позже нам придется сделать это вот так:
      windowRect.left = 100; windowRect.top = 100; windowRect.right = 400;
      windowRect.bottom = 400;
*/


/*      Строка ниже это прототип функции. Если вы помните, прототип
      функции это объявление функции, которое говорит компилятору,
      чего следует ожидать. Он будет знать, что ему нужно выделить
      память для функции с параметрами HWND, UINT, WPARAM, LPARAM;

      Обратите внимание, что в функции нет имен переменных, 
      например WndProc(HWND Hwnd, UINT UInt, WPARAM wParam,
      LPARAM lParam). Вы НЕ обязаны указывать имена переменных в
      прототипе функции, хотя в ваших функциях вам следует это делать.
      Как я говорил, компилятору нужно знать, из чего состоит
      функция, имена переменных для него не важны.

      LRESULT в начале функции означает:
      Из функции callback или window процедуры будет возвращено 
      32-битное значение. По-русски это значит, что мы хотим, чтобы
      значение, возвращаемое из функции было 32-битным.
      Вы будете использовать LRESULT на CALLBACK функции. Значение
      CALLBACK используется для функций windows и позволяет функции
      быть чем-то вроде указателя, чтобы вы могли присвоить
      функцию переменной CALLBACK. Сейчас это не играет большой 
      роли, но позже, когда вы увидите, как это используется,
      это будет иметь значение.
*/

//      Эта функция обрабатывает все оконные сообщения.
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);      


/*      Помните "main()"? Это функция main() для Windows.
      Она называется WinMain().

      WINAPI это "соглашение вызова Win32 API". Просто примем это
      пока что как должное. Пока достаточно знать, что мы должны
      ставить WINAPI перед WinMain(). А также мы указываем, что
      WinMain возвращает целое число. Функции WinMain() не нужен
      прототип, поэтому мы можем начинать писать для нее код.

      С этого места, почти что каждая переменная будет новой для вас.
      А также, к чему-то нужно будет привыкнуть. Позвольте мне объяснить
      значения этих перменных. Когда я изучал их, я не знал по настоящему,
      что они из себя представляют, я просто знал, что они нужны для 
      работы программы.

      HINSTANCE hInstance - содержит информацию об экземпляре приложения.
      Это потому что одновременно могут быть запущены 2 копии (экземпляра)
      той же самой программы.

      HINSTANCE hPrevInstance - содержит информацию о предыдущем 
      экземпляре приложения, и ее значение всегда равно NULL (нет 
      информации) для win32 приложений.

      PSTR szCmdLine - содержит информацию из командной строки.
      Например, как вы можете набрать "<имя программы> -l *.*"
      или что-то вроде того в DOS.
      Это если вы хотите передавать в ваше приложение командные
      строки DOS. PSTR это просто строка.

      int iCmdShow - содержит информацию о состоянии окна, например
      Maximized, Minimized, Hide и т.п.
*/

// Итак, вот наша "main()" для windows. Она обязательно должна быть в windows приложении.
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)                  
    {           
    
    HWND        hwnd;                  
      // HWND это ссылка на окно (handle to a window). Она используется,
      // чтобы отслеживать конкретное окно. Программы могут иметь много
      // окон. В этой у нас будет только одно.
            
    MSG         msg;
      // MSG  - переменная сообщений (MeSsaGe), чтобы хранить посылаемые
      // окну сообщения (если окно было щелкнуто мышью, закрыто, передвинуто и т.п.)

    WNDCLASSEX  wndclass;                                                      
      // WNDCLASSEX - эта переменная содержит всю информацию об окне 
      // (имя, значок, курсор, цвет, меню...)


    wndclass.cbSize        = sizeof (wndclass);                        
      // Здесь мы устанавливаем размер wndclass. Вы увидите это в windows программах
      // много раз. Мы используем функцию "sizeof()", чтобы сообщить windows
      // размер нашего класса.

    wndclass.style         = CS_HREDRAW | CS_VREDRAW;
      // Стиль, который мы хотим - это перерисовка по вертикали и горизонтали
      
    wndclass.lpfnWndProc   = WndProc;                                    
      // В этом месте мы сообщаем о нашей CALLBACK функции. Помните, выше
      // нашу функцию "WndProc"? Эта переменная просто говорит windows,
      // которую функцию нужно вызвать для проверки сообщений окна.
      
    wndclass.cbClsExtra    = 0;                                                
      // Мы не хотим выделять для класса дополнительные байты (переменная бесполезна для нас).
      
    wndclass.cbWndExtra    = 0;                                                
      // Еще одна бесполезная для нас вещь. Я полагаю, эти две в любом случае
      // нужно инициализировать в 0.
      
    wndclass.hInstance     = hInstance;                                    
      // Мы присваиваем hInstance нашему окну. И вновь, может быть запущено несколько
      // экземпляров той же программы, а эта переменная будет отслеживать текущий.

    wndclass.hIcon         = LoadIcon (NULL, IDI_WINLOGO);      
      // Мы вызываем функцию LoadIcon, которая возвращает информацию о значке,
      // который мы хотим. Я выбрал логотип windows. NULL это вместо hInstance.
      // В данном случае нам она не нужна.

    wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);      
      // Мы вызываем функцию LoadCursor, которая возвращает информацию о курсоре,
      // который мы хотим. Я выбрал стрелку. NULL это вместо hInstance.
      
    wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
      // Здесь мы устанавливаем цвет фона. GetStockObject() возвращает void,
      // поэтому мы должны преобразовать тип в HBRUSH, для совместимости
      // с переменной "hbrBackground".

    wndclass.lpszMenuName  = NULL;
      // У нас нет меню, поэтому установим это в NULL.
      
    wndclass.lpszClassName = "Window Class 1";                        
      // Здесь мы устанавливаем имя нашего класса, чтобы он отличался от других.
      // Это имя понадобится нам позже, когда мы будем создавать окно.

    wndclass.hIconSm       = LoadIcon (NULL, IDI_WINLOGO);      
      // Мы хотим значок windows logo. Это тот значок, который 
      // появляется в левом верхнем углу окна.


      RegisterClassEx (&wndclass);                                          
      // Нам нужно зарегистрировать наш оконный класс в системе windows.
      // Нам также нужно передать адрес wndclass в памяти, поэтому
      // мы используем "&".

      //      А теперь мы в действительности создадим окно.
      //      CreateWindow() возвращает ссылку на окно,
      //      которую мы сохраняем в нашей переменной "hwnd" типа HWND.

    hwnd = CreateWindow ("Window Class 1",            //      имя класса окна            
                                     "My First Window",            //  заголовок окна                  
                                     WS_OVERLAPPEDWINDOW,      //      стиль окна            
                                     windowRect.left,            //      начальное положение x (НОВОЕ) 
                                     windowRect.top,            //      начальное положение y (НОВОЕ)  
                                     windowRect.right,            //      начальное положение x (НОВОЕ)
                                     windowRect.bottom,            //      начальное положение y (НОВОЕ) 
                                     NULL,                              //      ссылка на родительское окно 
                                     NULL,                              //      ссылка на меню окна       
                                     hInstance,                        //      ссылка на экземпляр программы 
                                     NULL);                              //      для WndProc            

      /*      "Window Class 1" - имя класса окна.
            Это говорит фунции CreateWindow() использовать наш класс, определенный выше.

            "My First Window" - заголовок окна.
            Это имя появится в заголовке окна.

            WS_OVERLAPPEDWINDOW - стиль окна.
            Это значение говорит windows создать типичное окно
            (с опциями resize, minimize, close, и т.д.).

            windowRect.left - начальное положение x.
            Значение Х левого верхнего угла окна в экранных координатах.
            Чтобы установить положение окна, мы используем наш прямоугольник.
                        
              windowRect.top - начальное положение y.
            Значение Y левого верхнего угла окна в экранных координатах.
            Чтобы установить положение окна, мы используем наш прямоугольник.

              windowRect.right - начальное положение x.
            Значение Х правого нижнего угла окна в экранных координатах.
            Чтобы установить положение окна, мы используем наш прямоугольник.
            
              windowRect.bottom - начальное положение y.
            Значение Y правого нижнего угла окна в экранных координатах.
            Чтобы установить положение окна, мы используем наш прямоугольник.

            NULL - ссылка на родительское окно.
            Так как у нас нет родительского окна, мы устанавливаем NULL.

            NULL - ссылка на меню окна.
            У нас нет меню, поэтому устанавливаем в NULL.

            hInstance - ссылка на экземпляр программы.
            Мы просто передаем нашу hInstance из WinMain().
            Кстати, система Windows передает информацию в WinMain().

            NULL - если бы мы хотели передать переменную или структуру
            в "WndProc", мы бы сделали это здесь. (Я предпочитаю использовать
            глобальные переменные). Просто передаем NULL.
      */


    ShowWindow (hwnd, iCmdShow);                                          
      // Эта функция показывает наше окно. Мы передаем в нее ссылку на наше окно, в которой
      // теперь есть вся информация, и переменную iCmdShow функции WinMain().
      
    UpdateWindow (hwnd);                                                      
      // Эта функция выводит наше окно на экран.


      // Это наш главный цикл. Он будет продолжаться до тех пор, пока функция
      // GetMessage не вернет сообщение WM_QUIT, закрывающее программу.
      // Это произойдет, когда мы закроем окно.

    while (GetMessage (&msg, NULL, 0, 0))                              
    // Нам нужно передать адрес "msg", потому что GetMessage заполнает структуру "msg".
    // Мы передаем NULL для HWND, потому что тогда GetMessage проверяет ВСЕ окна,
    // которые используют нашу WndProc. И в конце мы передаем нули, они не важны.
    {                                                                                    
            TranslateMessage (&msg);                                          
            // Функция TranslateMessage() преобразовывает сообщения virtual-key в символьные.
            // В основном это означает, что функция преобразовывает их, чтобы windows 
            // смогла их понять.
            DispatchMessage (&msg);                                                
            // Функция DispatchMessage() передает сообщения в процедуру окна.
            // Это значит, что она обрабатывает сообщения, например если было сообщение
            // закрыть окно, она закрывает окно.
    }

      UnregisterClass("Window Class 1", hInstance);            
      // Нам нужно "отрегистрировать" наш оконный класс из системы Windows.
      // Делая это, мы освобождаем память, выделенную для регистрации оконного класса.
      
      return msg.wParam ;                                                            
      // Мы возвращаем wParam структуры "msg". Вот почему мы указали, что WinMain() 
      // возвращает int. wParam/lParam это 32-битный параметр сообщения.
      // В нем хранятся данные о сообщении. Позже вы увидите, как он используется.
}


// "Большинство того, что вверху, никогда не меняется."
// "WndProc это то, с чем обычно и приходится иметь дело."

/*      Это WndProc, что означает "Window Procedure" (оконная процедура).
      Эта функция обрабатывает оконные сообщения. Весь код выше обычно
      не меняется, когда мы пишем программу для windows, но WndProc
      это то, что вы действительно меняете, и она никогда не является
      той же самой. Поэтому ее важнее всего понять.

      У нас указано LRESULT CALLBACK. Еще раз, это означает, что функция
      возвращает 32-битное целочисленное значение, и является CALLBACK.
      Call back функция это все равно что указатель на функцию.
      Фактически это и есть указатель на функцию. Мы передаем адрес
      функции классу окна, и windows заполняет за нас все параметры.

      HWND это наша ссылка на окно, iMsg это сообщение, посылаемое
      windows. WPARAM и LPARAM хранят информацию о сообщении.
*/

LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{                          
      
      /*  Переменные STATIC - это переменные, которые не уничтожаются после выхода
            из функции. WndProc() вызывается миллион раз, и если бы переменные не
            были статическими (static), они бы инициализировались каждый раз      */
      
      static TEXTMETRIC textInfo;
      // Переменная TEXTMETRIC содержит информацию о шрифте. Мы используем ее
      // чтобы точно центрировать наш текст.
      
      static int length = 0;                                                      
      // Здесь будет храниться длина нашей строки.
      
      PAINTSTRUCT paintStruct;
      // Структура PAINTSTRUCT это то, что нам нужно для рисования с WM_PAINT.
      // Windows заполнит ее необходимыми данными за нас.
      
      HDC hdc = NULL;
      // HDC это ссылка на контекст устройства. Можно думать о нем как о ссылке
      // на кадровый буфер. Кадровый буфер находится в видеокарте и содержит
      // все постоянно обновляемые данные о изображении на экране.
      
      int x, y;                                                                        
      // Будут использоваться для размещения нашего текста.
      
      char szHello[]="Hello World!";                              
      // Создаем строку, которую будем печатать.


      // Это проверка, какое передается сообщение.
      switch (iMsg)                                                                  
    {      
            // Это сообщение посылается, когда создается окно.
            case WM_CREATE:                                                            
                  // Сюда мы помещаем код инициализации, потому что это выполняется только один раз.
                  
                  // Мы передаем hwnd (ссылку на окно) в GetWindowDC(). 
                  // Она возвращает ссылку на контекст устройства.
                  // Как правило, если мы хотим сделать что-нибудь с графикой, нам нужно HDC.
                  hdc = GetWindowDC(hwnd);                                    

                  // Здесь мы передаем наш новый hdc и textInfo в GetTextMetrics().
                  // Эта функция заполнит textInfo информацией о шрифте (ширина, высота и т.д)
                  GetTextMetrics(hdc, &textInfo);                              
            
                  // Определяем, сколько символов в строке.
                  length = strlen(szHello);                                    

                  // Так как мы выделили HDC с помощью GetWindowDC(), нам нужно освободить его,
                  // чтобы избежать утечки памяти.
                  ReleaseDC(hwnd, hdc);                                          

                  break;                                                                  


            // Это сообщение посылается, когда мы изменяем размер окна.
            case WM_SIZE:
                  
                  // Вызываем функцию, которая заполняет структуру RECT положением нашего окна.
                  // Это сообщение будет отправлено, если мы передвинем окно или изменим его
                  // положение. И тогда у нас будет свежая информация о положении окна.
                  GetWindowRect(hwnd, &windowRect);                        
                                                                                          
                  break;                                                                  


            // Это сообщение посылается в WndProc, когда окно нужно перерисовать.
            // Это происходит, когда мы передвинули окно, изменили его размер, раскрыли
            // на весь экран, или поместили поверх другое окно.
            case WM_PAINT:                                                            
                  
                  // Так мы получаем HDC для рисования. BeginPaint() возвращает hdc и
                  // заполняет структуру paintStruct. Как вы заметите, большинство
                  // функций требуют HWND. HWND передается из WinMain() в CALLBACK функцию
                  // WndProc.
                  hdc = BeginPaint(hwnd, &paintStruct);                  


                  /*      Здесь мы устанавливаем цвет текста. Мы передаем HDC и используем
                        макрос, называемый RGB(). Еще раз, макрос это НЕ функция, а просто
                        замена текста, которая создается с помощью "#define". Этот макрос
                        находится в <windows.h>.

                        Быстрый урок по RGB (Red-Green-Blue) содержится в конце этого файла.      */

                  SetTextColor(hdc, RGB(255, 0, 0));                        


                  /*      А теперь начинается математика. Это простейшая алгебра, поэтому не
                        паникуйте. Мы хотим разместить "Hello World!" по центру экрана.
                        Прежде всего, мы хотим узнать ширину окна. Чтобы узнать ширину
                        окна, мы вычитаем левую сторону из правой. Теперь, когда у нас есть
                        ширина, мы хотим найти половину ширины (т.е. центр), поэтому делим
                        ширину на два.

                        В самом начале правая сторона равна 500, левая - 100. И тогда
                        500 - 100 = 400. Делим это на 2 и получаем 200. x = 200                  */

                  x = (windowRect.right - windowRect.left) / 2;      

                  /*      Далее, если мы хотим текст точно по центру, а не чтобы он начинался
                        из центра, нам нужно знать ширину шрифта (ширину каждого символа
                        в пикселах) и сколько букв в строке. Я узнал, что ширина символа
                        равна 7, а длина 12 (12 букв в "Hello World!" включая пробел.)
                        И тогда, чтобы узнать ширину "Hello World!" в пикселах, мы умножаем
                        число символов на ширину символа. Затем делим на два для центрования.

                        Итак, 200 - ((12 * 7) / 2) = 158. Поэтому, наша координата Х 
                        начала строки равна 158.                  */

                  x = x - ((length * textInfo.tmAveCharWidth) / 2);


                  //      Теперь делаем то же самое для Y, но с другими числами.
                  //      Еще раз, (500 - 100) / 2 = 200;                  
                  y = (windowRect.bottom - windowRect.top) / 2;      
                  
                  
                  // Так как количество символов не имеет значения для Y, мы просто вычитаем
                  // половину высоты шрифта.
                  y = y - (textInfo.tmHeight / 2);                  
                                                                  
                  // Далее мы хотим напечатать текст. Мы используем TextOut(). Ее параметры
                  // (HDC, X, Y, строка, и длина строки)
                  
                  TextOut(hdc, x, y, szHello, length);                  
                  // Мы передаем hdc, координаты x и y, строку и ее длину. Вот оно!
                  // Текст по центру! Даже если вы измените размер окна. Каждый раз когда
                  // вы передвигаете или изменяете размер окна, вызывается WM_PAINT.
                  
                  // Теперь мы должны освободить память, которая была выделена для paintStruct.
                  EndPaint(hwnd, &paintStruct);
                  
                break;                                                                  


            // Это сообщение передается, когда пользователь закрывает окно.
            case WM_DESTROY:                                                      

                  PostQuitMessage(0);      
                  // Вы обязаны вызвать эту функцию или вам придется нажать control-alt-delete
                  // и закрыть программу вручную. 0 = WM_QUIT.
                  // Эта функция помещает сообщение в очередь сообщений.
                  // SendMessage() посылает сообщение, которое обрабатывается немедленно.
                  // Это вам просто для информации.
                  
                  break;                                                                  
      }                                                                              

      return DefWindowProc (hwnd, iMsg, wParam, lParam);      
      // Функция DefWindowProc вызывает оконную процедуру по умолчанию, чтобы обеспечить 
      // обработку по умолчанию тех оконных сообщений, которые не обрабатывает программа.
      // Эта функция позволяет быть уверенным, что каждое сообщение обрабатывается.
      // DefWindowProc вызывается с теми же параметрами, которые получает WndProc. 
      
}      // конец WndProc


/*      Вероятно, вы думаете: "И это все для какого-то окна и строки текста?" Да, да...
      Много людей не любят программирование windows, потому что программы очень большие.
      Когда вы разберетесь со всем этим, вы скорее всего поместите большинство всего
      этого в функцию, и вам не придется копировать или набирать все это снова. Как
      например, вы могли бы создать вашу собственную функцию создания окна, куда бы вы
      передали ширину, высоту, возможно заголовок, и что-нибудь еще. Эта функция делала
      бы все за вас одной строкой. Это очень удобно.  Программа, которую мы только что
      закончили, выглядела бы вот так:

      #include <windows.h>

      CreateMyWindow(100, 100, 400, 400, "My Window!");

      while(Messages())
            DisplayText("Hello World!", TEXT_CENTER);

      Вот так. Если вы напишете некоторые функции, вы сможете сделать все это тремя
      строками кода. Вы спросите, "а что если я захочу проверять другие сообщения
      windows?" Просто напишите функции и для них. Это того стоит. Вы создаете
      библиотеку, после чего вам не нужно будет обращаться к WndProc() или WinMain().
      Конечно, большинство людей любит работать с WndProc(). (либо они просто не
      хотят писать все эти функции.)

      Кстати, когда я учился в школе, нам нужно было создать игровую библиотеку.
      Наши программы были маленькими, потому что мы использовали библиотеки.
      У нас были функции для всего - рисования линий, треугольников, кругов,
      окон, растровых изображений...

      Мы делали игру pacman в windows со звуком, меню и всем остальным, и программа
      была достаточно маленькой. Трудно представить, какой бы она была без библиотек.

      *Быстрый урок по RGB*

      RGB означает Red Green Blue (красный, зеленый, синий). Это основные цвета.
      С помощью этих цветов вы можете получить любой цвет. В шкале RGB значение
      255 максимально. Как вы видите, в нашей программе мы использовали RGB(255, 0, 0);
      что сделало наш текст красным. Вот как работает макрос: RGB(интенсивность 
      красного, интенсивность зеленого, интенсивность синего);
      Если интенсивность красного равна 255 (максимальна), а интенсивности 
      зеленого и синего равны нулю, то итоговым цветом будет красный. А вот 
      зеленый: RGB(0, 255, 0); и синий: RGB(0, 0, 255), а также красный: RGB(255, 0, 0);
      Угадайте, а что такое RGB(0, 0, 0)? Что такое отсутствие цвета? А что такое
      отсутствие света? Темнота. Поэтому это будет черный цвет. А что тогда
      RGB(255, 255, 255)? Какой цвет имеет наибольшую интенсивность света? Белый.
      Теперь, как вы помните из рисования в начальных классах, если вы смешиваете
      цвета, то получаются другие. Точно также, как и для RGB(). Вот некоторые
      смешанные цвета. Фиолетовый: RGB(255, 0, 255), желтый: RGB(255, 255, 0),
      небесно-голубой: RGB(0, 255, 255). А если вы хотите понизить интенсивность
      цвета, просто уменьшайте значение, например RGB(0, 125, 0) для темно-зеленого.
      Я думаю, вы поняли смысл. Просто пробуйте комбинации, чтобы получить желаемый
      цвет.      
      
        
      *Быстрый урок по статическим переменным*

      Мы пишем static впереди двух наших переменных, потому что они инициализируются
      в WM_CREATE. WM_CREATE вызывается один раз. Если переменная не глобальная
      (не определена вне функции), то после ее завершения, переменная уничтожается
      и инициализируется снова после повторного вызова. Так как WndProc вызывается
      бесчисленное число раз, нам понадобилось сделать две переменные статическими,
      иначе они бы инициализировались каждый раз. В результате мы не получили бы
      нужную для WM_PAINT информацию.
              
*/

// © 2000-2002 GameTutorials         
// Перевод © 2004 Евгений Казеко
// www.gamecoder.kazeko.com
// evgeniy@kazeko.com

Скачать обучалку (Visual C++ 6)

Контекст устройства | Все обучалки раздела | Ввод с клавиатуры

[Главная] [С чего начать?] [Дистанционное обучение] [Статьи] [Обучалки] [Книги] [Софт] [Форум] [Ссылки] [О сайте]

Copyright © 2003-2005 Евгений Казеко. Все права защищены. E-mail: evgeniy@kazeko.com

Все о канкуне. Ознакомительный тур на кубу 2009. Остров ямайка. , натяжные потолки московская область , Российские двери входные с любой отделкой.