Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Нестандартная кнопка в виде рисунка (BMP)  (Прочитано 17255 раз)
0 Пользователей и 1 Гость смотрят эту тему.
sxd
Участник

ru
Offline Offline

« : 09-03-2007 17:07 » 

Добрый вечер. Помогите создать нестандартную кнопку в виде рисунка (BMP), с учётом того что, кнопка должна визуально реагировала на нажатие и наведение. Я искал в сети, перерыл ВСЁ, но всё что нашёл всё на MFC. Поделитесь пожалуйста примерчиком или ссылкой на код WINAPI? Буду весьма признателен за помощь!!!

P.S.: Да и выкладываю, на мой взгляд, наиболее предпочтительный вариант на MFC, кто знает может кто-нибудь и сможет перевести на WinAPI. Возможно ли перевести код на WINAPI?

* Button.rar (23.91 Кб - загружено 1000 раз.)
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 09-03-2007 17:18 » 

Ну для начал придется создать окно формы рисунка, а потом на это окно уже рисунок положишь.  Для этого юзай функции CreateWindow(), Get | Set WindowRect, CreateRectRgn и т.п. А потом когда будешь создавать функцию обработчик сообщений окна, обрабатывай  нажатие и наведение, подобно, как это делал с теми же кнопками Ага.
Записан

ещё один вопрос ...
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #2 : 09-03-2007 17:27 » 

Посмотри на форуме. Я по крайней мере несколько раз кидал компоненты написанные на чистом WinAPI. Вот например https://forum.shelek.ru/index.php/topic,3741.msg69657.html#msg69657
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
sxd
Участник

ru
Offline Offline

« Ответ #3 : 09-03-2007 19:04 » 

Не, ребят вот гляньте код создаёт окно в виде рисунка, только вот кнопку тоже в виде рисунка поместить на это окно неправильной формы - неудалось, а так ведь по идеи на этом окне подобным способом можно сделать неправильную кнопку.

А вот и код:
Код:
#define _WIN32_WINNT 0x0500
#include <stdafx.h>
#include <windows.h>
#include <shlwapi.h>
#include <commctrl.h>
#include <resource.h>

#pragma comment(lib, "comctl32.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "shlwapi.lib")

typedef void (CALLBACK*MY_FUNC)(HWND,int,int,int);
const int LMA_ALPHA = 2, LMA_COLORKEY = 1, WS_EX_LAYERED = 0x80000;
int WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

HINSTANCE hInstance;
WNDCLASS wc;
MSG msg;
RECT Rects;
PAINTSTRUCT ps;
HDC hDc;
HDC hMemDC;
HRGN hRgn, ResRgn;
HDC myDC;
HBITMAP hBitmap;
MY_FUNC SetLayeredWindowAttributes;
int Alpha;
BITMAP bi;
BYTE bpp;
DWORD TransPixel;
DWORD pixel;
int startx;
int i, j;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
        HWND hWnd;
hInstance = GetModuleHandle(0);

        wc.style                = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc          = (WNDPROC) WndProc;
wc.cbClsExtra           = 0;
wc.cbWndExtra           = 0;
wc.hInstance            = hInstance;
wc.hIcon                = NULL;
wc.hCursor              = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground        = 0;
wc.lpszMenuName         = NULL;
wc.lpszClassName        = "Test";
if(!RegisterClass(&wc))
{
MessageBox(0,"Невозможно зарегестрировать класс.","Error",MB_OK|MB_ICONERROR);
ExitProcess(0);
};

int iWinX = 357;
int iWinY = 595;

hWnd = CreateWindow("Test", "TestWindow", CW_USEDEFAULT, GetSystemMetrics (SM_CXSCREEN)/2-iWinX/2,
GetSystemMetrics (SM_CYSCREEN)/2-iWinY/2,
iWinX, iWinY, NULL, NULL, hInstance, NULL);
        if(!hWnd)
{
MessageBox(0, "Возникла ошибка при создании окна.", "Error", MB_OK|MB_ICONERROR);
ExitProcess(0);
        };

        SetFocus(hWnd);

while (msg.message != WM_QUIT)
{
GetMessage(&msg, NULL, 0, 0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
int WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
SetWindowLongA(hWnd, GWL_EXSTYLE, WS_EX_LAYERED | GetWindowLongA(hWnd, GWL_EXSTYLE));
SetLayeredWindowAttributes = (MY_FUNC)GetProcAddress(GetModuleHandleA("User32.dll"), "SetLayeredWindowAttributes");
hDc = GetWindowDC(hWnd);
hMemDC = CreateCompatibleDC(hDc);
SelectObject(hMemDC, hBitmap);
GetWindowRect(hWnd, &Rects);
GetClientRect(hWnd, &Rects);
myDC = hMemDC;
hBitmap = (HBITMAP)LoadImage(NULL, "bitmap3.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (!hBitmap) return NULL;
HRGN Rgn, ResRgn = CreateRectRgn(0, 0, 0, 0);
GetObject(hBitmap, sizeof(BITMAP), &bi);
bpp = bi.bmBitsPixel >> 3;
BYTE *pBits = new BYTE[ bi.bmWidth * bi.bmHeight * bpp ];
int  p = GetBitmapBits( hBitmap, bi.bmWidth * bi.bmHeight * bpp, pBits );
TransPixel = *(DWORD*)pBits;
TransPixel <<= 32 - bi.bmBitsPixel;
for (i = 0; i < bi.bmHeight; i++)
{
startx=-1;
for (j = 0; j < bi.bmWidth; j++)
{
pixel = *(DWORD*)(pBits + (i * bi.bmWidth + j) * bpp) << (32 - bi.bmBitsPixel);
if (pixel != TransPixel)
{
if (startx < 0)
{
startx = j;
}
else if (j == (bi.bmWidth - 1))
{
Rgn = CreateRectRgn( startx, i, j, i + 1 );
CombineRgn( ResRgn, ResRgn, Rgn, RGN_OR);
startx =- 1;
}
} else if (startx >= 0)
{
Rgn = CreateRectRgn(startx, i, j, i + 1);
CombineRgn(ResRgn, ResRgn, Rgn, RGN_OR);
startx =- 1;
}
}
}
delete pBits;
SetWindowRgn(hWnd, ResRgn, TRUE);
InvalidateRect(hWnd, 0, false);
Alpha = 0;
while(Alpha != 255)
{
if(Alpha == 45)
{
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
}
Sleep(10);
SetLayeredWindowAttributes(hWnd, Alpha, Alpha, LMA_COLORKEY | LMA_ALPHA);
Alpha = Alpha + 15;
}
ShowWindow(hWnd, SW_SHOW);
Alpha = 240;
ReleaseDC(hWnd, hDc);
DeleteDC(hMemDC);
break;
}
case WM_DESTROY:
{
    DeleteObject(hBitmap);
PostQuitMessage(0);
break;
}
case WM_PAINT:
{
GetClientRect(hWnd, &Rects);
hDc = BeginPaint(hWnd, &ps);
hMemDC = CreateCompatibleDC(hDc);
SelectObject(hMemDC, hBitmap);
BitBlt(hDc, 0, 0, Rects.right, Rects.bottom, hMemDC, 0, 0, SRCCOPY);
DeleteDC(hMemDC);
EndPaint(hWnd, &ps);
SetLayeredWindowAttributes(hWnd, Alpha, Alpha, LMA_COLORKEY | LMA_ALPHA);
break;
}
case WM_LBUTTONDOWN:
{
ReleaseCapture();
SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
break;
}
case WM_CLOSE:
{
Alpha = 255;
while(Alpha != 0)
{
Sleep(15);
SetLayeredWindowAttributes(hWnd, Alpha, Alpha, LMA_COLORKEY | LMA_ALPHA);
Alpha = Alpha - 15;
};
PostQuitMessage(0);
break;
}
default:
{
return (DefWindowProc(hWnd, message, wParam, lParam));
break;
}
break;
}
 return 0;
}

Ну что думаете по этому поводу? Есть варианты приаттачить кнопку неправилной формы к етому окошку?
Записан
sxd
Участник

ru
Offline Offline

« Ответ #4 : 09-03-2007 19:06 » 

Да там в коде ещё фитча шоб медленно появлялась!
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 10-03-2007 07:12 » 

Попробуй добавить подобное
Код:
RECT rct;
HRGN FormRgn;
GetWindowRect(Control,&rct);
FormRgn=CreateEllepticRgn(.....); //Какие хошь размеры ставишь
SetWindowRgn(Control, FormRgn, TRUE);
Control - элемент управления. Короче считай, что кнопка твоя. Этот код должен работать на 100%.
Записан

ещё один вопрос ...
sxd
Участник

ru
Offline Offline

« Ответ #6 : 10-03-2007 14:53 » 

Привет nikedeforest! Спасибо конечно за помощь, но вот возникло два вопроса - первый не вижу в коде чтоб гдето присутствовала переменная типа HBITMAP для картинки, второй CreateEllepticRgn() этой функции компилятор не знает, да и по названию можно судить, что она создаёт регион окна в форме элипса, у меня же задача сделать неправильную(элипсовидную) кнопку в виде рисунка.

Здесь вижу два варианта:
1. первый создать обыкновенную прямоугольную кнопку, но BMP - рисунок кнопки: на прямоугольном фоне окна поместить нарисованный овал, таким образом сама кнопка квадратная, но так как она сливается с фоном окна мы видим овальную кнопку, при наведении - отлавливаем это и заменяем BMP на другую, как бы нажатую.
2. второй как мне кажется сложнее надо создать овальный регион окна или в виде рисунка и загрузить туда кнопку.
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 10-03-2007 15:37 » 

Я херею блин!!!  Я тебе показал как сдлелать овальным контрол. По этому образу и подобию ты можешь сделать контрол любой формы (не только овальным). Ну и блин уж рисунок на конпку положить ты вроде знаешь как, поэтом и нет тут никакого HBITMAP.

По поводу второго пункта. Я тебе предложил до этого вариант - создать окно овальным, положить на него рисунок и НАДЕЛИТЬ ЕГО СВОЙСТВАМИ КНОПКИ, а не кнопку загружать в него (это если не знаешь как кнопку сделать овальной). Потом я тебе показал как сделать кнопку овальной. Чего тебе еще непонятно-то???
Записан

ещё один вопрос ...
sxd
Участник

ru
Offline Offline

« Ответ #8 : 11-03-2007 18:27 » new

Вот попытался сделать кнопку как бы вроде получилось, но как-то коряво и косяков много:

1. когда по картинке тыкаешь мышкой иногда выскакивает реальная кнопка
2. при наведении картинка не сразу заменяется другой
3. в обработчике нажатия на кнопку MessageBox не выводится

Выкладываю проект посмотрите на досуге может найдёте косяки, да и я тоже щас посижу ещё поищю...
Пожалуста помогите очень важно...

* SxdButtonTest.rar (69.88 Кб - загружено 977 раз.)
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines