ПЕРЕЛІК ДИСЦИПЛІН:
  • Адміністративне право
  • Арбітражний процес
  • Архітектура
  • Астрологія
  • Астрономія
  • Банківська справа
  • Безпека життєдіяльності
  • Біографії
  • Біологія
  • Біологія і хімія
  • Ботаніка та сільське гос-во
  • Бухгалтерський облік і аудит
  • Валютні відносини
  • Ветеринарія
  • Військова кафедра
  • Географія
  • Геодезія
  • Геологія
  • Етика
  • Держава і право
  • Цивільне право і процес
  • Діловодство
  • Гроші та кредит
  • Природничі науки
  • Журналістика
  • Екологія
  • Видавнича справа та поліграфія
  • Інвестиції
  • Іноземна мова
  • Інформатика
  • Інформатика, програмування
  • Юрист по наследству
  • Історичні особистості
  • Історія
  • Історія техніки
  • Кибернетика
  • Комунікації і зв'язок
  • Комп'ютерні науки
  • Косметологія
  • Короткий зміст творів
  • Криміналістика
  • Кримінологія
  • Криптология
  • Кулінарія
  • Культура і мистецтво
  • Культурологія
  • Російська література
  • Література і російська мова
  • Логіка
  • Логістика
  • Маркетинг
  • Математика
  • Медицина, здоров'я
  • Медичні науки
  • Міжнародне публічне право
  • Міжнародне приватне право
  • Міжнародні відносини
  • Менеджмент
  • Металургія
  • Москвоведение
  • Мовознавство
  • Музика
  • Муніципальне право
  • Податки, оподаткування
  •  
    Бесплатные рефераты
     

     

     

     

     

     

         
     
    Робота з регіонами в Visual C ++
         

     

    Інформатика, програмування

    Робота з регіонами в Visual C + +

    Vander Nunes

    У Win32 API є набір функцій для роботи з регіонами. За допомогою регіонів Ви можете створювати різні поверхні, використовуючи тільки стандартні геометричні фігури. Ну а далі все залежить від Вашої вигадки.

    Отже, приступимо до визначень:

    HRNG:

    Це всього лише тип даних, що означає "Хендлі регіону ". Такий Хендлі буде потрібно для кожного регіону, з яким Ви захочете працювати.

    Приклад використання:

    HRGN hRegion = CreateRectRgn (x, y, x +128, y +128);

    Після завершення роботи з регіоном, необхідно видалити об'єкт, пов'язаний з регіоном за допомогою функції DeleteObject ().

    CombineRgn, CreateEllipticRgn, CreateEllipticRgnIndirect, CreatePolygonRgn, CreatePolyPolygonRgn, CreateRectRgn, CreateRectRgnIndirect, CreateRoundRectRgn, EqualRgn, ExtCreateRegion, FillRgn, FrameRgn, GetPolyFillMode, GetRegionData, GetRgnBox, InvertRgn, OffsetRgn, PaintRgn, PtInRegion, RectInRegion, SetPolyFillMode.

    Це основні функції, які призначені для створення та роботи з регіонами. Як видно з назв, регіони можна створювати круглі, квадратні, а також будь-якої іншої форми.

    SetWindowRgn

    За допомогою цієї функції можна прикріпити регіон до будь-якого вікна. Наприклад, після використання цієї функції, вікно може виглядати наступним чином:

    Щоб виконати таке з вікном, знадобляться наступні функції:

    // ця функція створює цілий регіон.

    HRGN CreateEllipticRgn (

    int nLeftRect, //X-координата верхнього-лівого кута

    int nTopRect, //Y-координата верхнього-лівого кута

    int nRightRect, //X-координата нижнього-правого кута

    int nBottomRect// y-координата нижнього-правого кута

    );

    // ця функція поєднує два регіони

    int CombineRgn (

    HRGN hrgnDest, //Хендлі кінцевого регіону

    HRGN hrgnSrc1, //Хендлі вихідного регіону

    HRGN hrgnSrc2, //Хендлі вихідного регіону

    int fnCombineMode// режим сполучення регіонів

    );

    // ця функція прикріплює регіон до вікна.

    // щоб прибрати регіон з вікна, треба замість Хендлі регіону поставити NULL.

    int SetWindowRgn (

    HWND hWnd,// Хендлі вікна, на яке буде встановлений регіон

    HRGN hRgn,// Хендлі регіону

    BOOL bRedraw //Прапор перемальовування вікна

    );

    Ну а тепер поглянемо на реальний код, який демонструє створення вікна, зображення якого наведено вище:

    // --------------------------------------------- -----

    // Створюємо круглий регіон.

    // Використовуємо негативну початкову координату, щоб наш еліпс

    // захопив заголовок вікна.

    // --------------------------------------------- -----

    HRGN hRegion1 = CreateEllipticRgn (20, -20,190,150);

    // --------------------------------------------- -----

    // створюємо ще один круглий регіон в іншому місці.

    // --------------------------------------------- -----

    HRGN hRegion2 = CreateEllipticRgn (140,100,300,240);

    // --------------------------------------------- -----

    // склеюємо два регіони, щоб зробити новий регіон.

    // підсумковий регіон буде поміщений в region1,

    // подібно операції:

    //

    // hRegion1 = hRegion1 + hRegion2.

    //

    // у функції CombineRgn () можна використовувати набір операцій RGN_.

    // --------------------------------------------------

    CombineRgn (hRegion1, hRegion1, hRegion2, RGN_OR);

    // --------------------------------------------------

    // прикріплюємо регіон до вікна

    // --------------------------------------------------

    SetWindowRgn (hWnd, hRegion1, true);

    // --------------------------------------------------

    // видаляємо об'єкти регіонів

    // --------------------------------------------------

    DeleteObject (hRegion1);

    DeleteObject (hRegion2);

    Щоб повернути вікно в нормальний стан (без регіону), скористайтеся наступною функцією:

    SetWindowRgn (hWnd, NULL, true);

    Завантажити зразок - 13Кб

    СКІН

    Тема скінів досить популярна в програмуванні. При допомоги скінів ми можемо надати стандартного вікна привабливий вигляд:

    Для цього необхідний бітмапами, який заповнить все вікно. На наведеній картинці використовується вікно розміром 320х240 і такого ж розміру бітмапами.

    Давайте створимо невелике демонстраційне додаток. Нижче наведено кроки, які потрібно буде виконати:

    1 - Завантажуємо бітмапами;

    2 - Створюємо контекст пристрою для скіна і вибираємо в ньому бітмапами;

    3 - Створюємо перемикач між нормальним режимом і скіном;

    4 - приховує заголовок вікна і блокуємо зміна його розмірів у режимі скіна;

    5 - Показуємо заголовок вікна і розблокуємо його при вихід з режиму скіна;

    6 - обробляємо перемальовування скіна в повідомленні WM_PAINT;

    7 - обробляємо повідомлення WM_LBUTTON, щоб користувач міг перетягувати вікно за будь-яку частину в режимі скіна;

    А тепер кожен крок докладніше:

    1 - Завантажуємо бітмапами:

    // -------------------------------------------------- ---------------------

    // завантажуємо бітмапами скіна з ресурсу

    // -------------------------------------------------- ---------------------

    hSkinBmp = LoadBitmap (hInstance, MAKEINTRESOURCE (IDB_SKIN ));

    if (! hSkinBmp) return -1;

    Як видно з коду, нічого складного. Звичайно можна завантажувати зображення інших форматів, але це тема іншої статті.

    2 - Створюємо контекст пристрою для скіна і вибираємо в ньому бітмапами:

    // -------------------------------------------------- ---------------------

    // створюємо контекст пристрою для скіна

    // -------------------------------------------------- ---------------------

    dcSkin = CreateCompatibleDC (0);

    // --------------------------------------------- --------------------------

    // вибираємо бітмапами для скіна

    // -------------------------------------------------- ---------------------

    hOldBmp = (HBITMAP) SelectObject (dcSkin, hSkinBmp);

    Не забудьте звільнити ці об'єкти перед тим як Ваше додаток завершить свою роботу.

    3 - Створюємо перемикач між нормальним режимом і скіном:

    case VK_SPACE:

    (

    if (! bRegioned)

    RegionMe ();

    else

    UnRegionMe ();

    break;

    )

    Цей фрагмент коду необходмимі помістити в головну віконну процедуру в обробник повідомлення WM_KEYDOWN. Тут використовуються два невеликі власні функції RegionMe () і UnregionMe () для перемикання режиму.

    4 - приховує заголовок вікна і блокуємо зміна його розмірів у режимі скіна:

    // -------------------------------------------------- ----------------------

    // Створюємо основний регіон і встановлюємо його на вікно.

    // -------------------------------------------------- ----------------------

    void RegionMe ()

    (

    // --------------------------------------------- -----

    // створюємо цілий регіон і використовуємо негативну

    // координату, щоб регіон захопив заголовок вікна.

    // --------------------------------------------------

    HRGN hRegion1 = CreateEllipticRgn (20, -20,190,150);

    OffsetRgn (hRegion1, GetSystemMetrics (SM_CXBORDER) * 4, GetSystemMetrics (SM_CYCAPTION ));

    // --------------------------------------------- -----

    // створюємо другий регіон в іншому місці.

    // --------------------------------------------------

    HRGN hRegion2 = CreateEllipticRgn (140,100,300,240);

    OffsetRgn (hRegion2, GetSystemMetrics (SM_CXBORDER) * 4, GetSystemMetrics (SM_CYCAPTION ));

    // --------------------------------------------- -----

    // поєднуємо два регіони за принципом:

    // hRegion1 = hRegion1 + hRegion2.

    // --------------------------------------------------

    CombineRgn (hRegion1, hRegion1, hRegion2, RGN_OR);

    // --------------------------------------------- -----

    // прикріплюємо підсумковий регіон до вікна

    // --------------------------------------------- -----

    SetWindowRgn (hWnd, hRegion1, true);

    // --------------------------------------------- -----

    // видаляємо об'єкти регіонів

    // --------------------------------------------- -----

    DeleteObject (hRegion1);

    DeleteObject (hRegion2);

    // --------------------------------------------- -----

    // змінюємо стиль вікна ( "забрали заголовка)

    // --------------------------------------------------

    DWORD dwStyle = GetWindowLong (hWnd, GWL_STYLE);

    dwStyle & = ~ (WS_CAPTION | WS_SIZEBOX);

    SetWindowLong (hWnd, GWL_STYLE, dwStyle);

    // --------------------------------------------- -----

    // перемальовує вікно, а так само прибираємо рамку вікна, щоб

    // щоб не можна було міняти його розмір

    // --------------------------------------------------

    InvalidateRect (hWnd, NULL, TRUE);

    SetWindowPos (hWnd, NULL, 0,0,320,242, SWP_NOMOVE | SWP_NOZORDER);

    // --------------------------------------------- -----

    // встановлюємо прапорець, тільки для того, щоб додаток знало про зміну.

    // --------------------------------------------- -----

    bRegioned = true;

    )

    5 - Показуємо заголовок вікна і розблокуємо його при вихід з режиму скіна:

    // -------------------------------------------------- ----------------------

    // Прибираємо регіон з вікна

    // -------------------------------------------------- ----------------------

    void UnRegionMe ()

    (

    // --------------------------------------------- -----

    // Прибираємо регіон з вікна

    // --------------------------------------------- -----

    SetWindowRgn (hWnd, NULL, true);

    // --------------------------------------------- -----

    // міняємо стиль вікна (знову показуємо заголовок)

    // --------------------------------------------------

    DWORD dwStyle = GetWindowLong (hWnd, GWL_STYLE);

    dwStyle | = WS_CAPTION | WS_SIZEBOX;

    SetWindowLong (hWnd, GWL_STYLE, dwStyle);

    // --------------------------------------------- -----

    // перемальовує вікно і повертаємо на місце рамку вікна, щоб можна було

    // змінювати його розмір

    // --------------------------------------------------

    InvalidateRect (hWnd, NULL, TRUE);

    SetWindowPos (hWnd, NULL, 0,0,320,240, SWP_NOMOVE | SWP_NOZORDER);

    // --------------------------------------------- -----

    // встановлюємо прапорець.

    // --------------------------------------------- -----

    bRegioned = false;

    )

    6 - обробляємо перемальовування скіна в повідомленні WM_PAINT:

    case WM_PAINT:

    (

    PAINTSTRUCT ps;

    BeginPaint (hWnd, & ps);

    // малюємо скін на вікні

    if (bRegioned) SkinMe (ps.hdc);

    // малюємо текст

    SetBkMode (ps.hdc, TRANSPARENT);

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

    TextOut (ps.hdc, 115,90, "Press SPACE", 11);

    EndPaint (hWnd, & ps);

    break;

    )

    Функція SkinMe () викликається тільки в тому випадку, якщо додаток знаходиться в режимі скіна (bRegioned).

    Функція SkinMe () виглядає наступним чином:

    void SkinMe (HDC dc)

    (

    BitBlt (dc, 0,0,320,240, dcSkin, 0,0, SRCCOPY);

    )

    7 - обробляємо повідомлення WM_LBUTTON, щоб користувач міг перетягувати вікно за будь-яку частину в режимі скіна:

    case WM_LBUTTONDOWN:

    (

    // -------------------------------------------------- -------

    // Посилаємо повідомлення вікна, щоб воно думало, що скликали на його заголовку.

    // -------------------------------------------------- -------

    if (bRegioned) SendMessage (hWnd, WM_NCLBUTTONDOWN, HTCAPTION, NULL);

    break;

    )

    Естевственно, що це повідомлення надсилається тільки коли вікно в режимі скіна.

    Завантажити исходник - 52Кб

    Складні регіони

    Прості геометричні фігурки це звичайно добре. А що робити, якщо треба створити регіон складної форми, наприклад у вигляді руки:

    Щоб зробити подібне, нам прийдеться наваяли невелику функцію, яка буде сканувати бітмапами і створювати з нього попіксельно регіон з прозорістю. Далі такий регіон буде достатньо причепити до вікна.

    // -------------------------------------------------- --------------------

    // Функція сканує бітмапами і повертає необхідну нам регіон.

    // Звільнити об'єкт регіону потрібно буде самостійно ...

    // -------------------------------------------------- --------------------

    HRGN ScanRegion (HBITMAP pBitmap, BYTE jTranspR, BYTE jTranspG, BYTE jTranspB)

    (

    // ширина і висота бітмапами

    WORD wBmpWidth, wBmpHeight;

    // кінцевий і тимчасовий регіони

    HRGN hRgn, hTmpRgn;

    // 24-бітові пікселі з бітмапами

    BYTE * pPixels = Get24BitPixels (pBitmap, & wBmpWidth, & wBmpHeight);

    if (! pPixels) return NULL;

    // створюємо робочий регіон

    hRgn = CreateRectRgn (0,0, wBmpWidth, wBmpHeight);

    if (! hRgn) (delete pPixels; return NULL;)

    // -------------------------------------------------- -------

    // скануємо бітмапами

    // -------------------------------------------------- -------

    DWORD p = 0;

    for (WORD y = 0; y

    (

    for (WORD x = 0; x

    (

    BYTE jRed = PPixels [p 2];

    BYTE jGreen = pPixels [p 1];

    BYTE jBlue = PPixels [p 0];

    if (jRed == jTranspR & & jGreen == jTranspG & & jBlue == jTranspB)

    (

    // видаляємо прозорий колір з регіону

    hTmpRgn = CreateRectRgn (x, y, x +1, y +1);

    CombineRgn (hRgn, hRgn, hTmpRgn, RGN_XOR);

    DeleteObject (hTmpRgn);

    )

    // наступний піксель

    p + = 3;

    )

    )

    // звільняємо пікселі

    delete pPixels;

    // повертаємо регіон

    return hRgn;

    )

    Як видно з коду, спершу створюється квадратний регіон такого ж розміру як і бітмапами, переданий у функцію як параметр. Потім відбувається сканування кожного пікселя і, якщо перебуває піксель такого ж кольору як і зазначений, то цей піксель виключається з регіону.

    Для демонстрації вищеописаного алгоритму була створена утиліта RegionCreator, яка являє собою консольний застосунок що працює з графічними файлами.

    Завантажити RegionCreator - 19Кб

    Запускається ця утилітка наступним чином:

    regioncreator

    bitmap.bmp: сам бітмапами

    r, g, b: прозорий колір (в десятковому вигляді: 255 255 255)

    Завантаження складних регіонів

    Після того, як бітмапами буде оброблений утилітки, його можна помістити в додаток як ресурс і завантажити в такий спосіб:

    // шукаємо ресурс для нашого скіна.

    HRSRC hrSkin = FindResource (hInstance, MAKEINTRESOURCE (IDB_SKIN), "BINARY ");

    if (! hrSkin) return false;

    // завантажуємо стандартний "BINARY" ресурс.

    LPRGNDATA pSkinData = (LPRGNDATA) LoadResource (hInstance, hrSkin);

    if (! pSkinData) return false;

    // створюємо регіон.

    HRGN rgnSkin = ExtCreateRegion (NULL, SizeofResource (NULL, hrSkin), pSkinData);

    // звільняємо виділений ресурс

    FreeResource (pSkinData);

    Після цього, регіон досить буде причепити до вікна. І не забудьте видалити регіон перед завершенням програми командою DeleteObject (rgnSkin).

    У висновку, непогано було б укласти весь вищенаведений матеріал в клас, щоб код зручніше читався:

    Удачи!

    Список літератури

    Для підготовки даної роботи були використані матеріали з сайту http://www.realcoding.net/

         
     
         
    Реферат Банк
     
    Рефераты
     
    Бесплатные рефераты
     

     

     

     

     

     

     

     
     
     
      Все права защищены. Reff.net.ua - українські реферати ! DMCA.com Protection Status