Сейчас на форуме: asfa, vsv1 (+5 невидимых)

 eXeL@B —› Вопросы новичков —› Дэбильный вопрос по програмированию
Посл.ответ Сообщение

Ранг: 419.0 (мудрец), 647thx
Активность: 0.460.51
Статус: Участник
"Тибериумный реверсинг"

Создано: 25 декабря 2015 20:21
· Личное сообщение · #1

Когда-то давно отрисовывал цветные BMP картинки с прозрачным фоном. Вроде не сложно, но у меня нихрена не получаетцо! ЗАДОЛБАЛО!

Короч посл действий:
Стянул DrawTransparentBitmap с просторов инета
Code:
  1. DrawTransparentBitmap(HDC hdc, HBITMAP hBitmap, short xStart,
  2.                            short yStart, COLORREF cTransparentColor)
  3.    {
  4.    BITMAP     bm;
  5.    COLORREF   cColor;
  6.    HBITMAP    bmAndBack, bmAndObject, bmAndMem, bmSave;
  7.    HBITMAP    bmBackOld, bmObjectOld, bmMemOld, bmSaveOld;
  8.    HDC        hdcMem, hdcBack, hdcObject, hdcTemp, hdcSave;
  9.    POINT      ptSize;
  10.  
  11.    hdcTemp = CreateCompatibleDC(hdc);
  12.    SelectObject(hdcTemp, hBitmap);
  13.  
  14.    GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
  15.    ptSize.= bm.bmWidth;
  16.    ptSize.= bm.bmHeight;
  17.    DPtoLP(hdcTemp, &ptSize, 1);
  18.                                     
  19.    hdcBack   = CreateCompatibleDC(hdc);
  20.    hdcObject = CreateCompatibleDC(hdc);
  21.    hdcMem    = CreateCompatibleDC(hdc);
  22.    hdcSave   = CreateCompatibleDC(hdc);
  23.  
  24.    bmAndBack   = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
  25.  
  26.  
  27.    bmAndObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
  28.  
  29.    bmAndMem    = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
  30.    bmSave      = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
  31.  
  32.  
  33.    bmBackOld   = (HBITMAP)SelectObject(hdcBack, bmAndBack);
  34.    bmObjectOld = (HBITMAP)SelectObject(hdcObject, bmAndObject);
  35.    bmMemOld    = (HBITMAP)SelectObject(hdcMem, bmAndMem);
  36.    bmSaveOld   = (HBITMAP)SelectObject(hdcSave, bmSave);
  37.  
  38.    SetMapMode(hdcTemp, GetMapMode(hdc));
  39.  
  40.    BitBlt(hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY);
  41.  
  42.    cColor = SetBkColor(hdcTemp, cTransparentColor);
  43.  
  44.    BitBlt(hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0,
  45.           SRCCOPY);
  46.  
  47.    SetBkColor(hdcTemp, cColor);
  48.  
  49.  
  50.    BitBlt(hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0,
  51.           NOTSRCCOPY);
  52.  
  53.  
  54.    BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart,
  55.           SRCCOPY);
  56.  
  57.    BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);
  58.  
  59.  
  60.    BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
  61.  
  62.  
  63.    BitBlt(hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT);
  64.  
  65.  
  66.    BitBlt(hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0,
  67.           SRCCOPY);
  68.  
  69.  
  70.    BitBlt(hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);
  71.  
  72.  
  73.    DeleteObject(SelectObject(hdcBack, bmBackOld));
  74.    DeleteObject(SelectObject(hdcObject, bmObjectOld));
  75.    DeleteObject(SelectObject(hdcMem, bmMemOld));
  76.    DeleteObject(SelectObject(hdcSave, bmSaveOld));
  77.  
  78.  
  79.    DeleteDC(hdcMem);
  80.    DeleteDC(hdcBack);
  81.    DeleteDC(hdcObject);
  82.    DeleteDC(hdcSave);
  83.    DeleteDC(hdcTemp);
  84.    }


Вызываю её в MFC:
Code:
  1. CDC* dc;
  2.         dc=GetWindowDC();
  3.                  CBitmap A_EXELAB;
  4.                         A_EXELAB.LoadBitmap(IDB_EXELAB);
  5. DrawTransparentBitmap(dc->m_hDC,  
  6.                          A_EXELAB,  
  7.                          10, 
  8.                          20, 
  9.                          0x00FFFFFF);

Да ни фига не отрисовывает в окне - хотя вроде всё ок должно быть! Кто просвятитъ? Мож в HDC явный косяк? Или замуты с owner_dwar?? Заранее БОЛЬШОЕ СПАСИБО!




Ранг: 324.3 (мудрец), 222thx
Активность: 0.480.37
Статус: Участник

Создано: 25 декабря 2015 20:34 · Поправил: DenCoder
· Личное сообщение · #2

Когда-то баловался с капчей, тоже загружал картинки bmp, jpg, tif...

Это код загрузки картинки
Code:
  1.          RECT r;
  2.          ::GetClientRect(Picture.m_hWnd, &r);
  3.  
  4.          if(gpImage) delete gpImage;
  5.  
  6.          int Index = BitmapList.GetCurSel();
  7.          CString cs;
  8.          BitmapList.GetText(Index, cs);
  9.  
  10.          char CurDir[0x100];
  11.          GetCurrentDirectory(0x100, CurDir);
  12.          strcat(CurDir, "");
  13.          cs.Insert(0, CurDir);
  14.          
  15.          char* Buffer = cs.GetBuffer();
  16.          WCHAR* wBitmapFileName;
  17.          int len = MultiByteToWideChar(CP_ACP, 0, Buffer, -1, NULL, 0);
  18.          wBitmapFileName = new WCHAR[len];
  19.          MultiByteToWideChar(CP_ACP, 0, Buffer, -1, wBitmapFileName, len * 2);
  20.  
  21.          Status status;
  22.          gpImage = Bitmap::FromFile(wBitmapFileName);
  23.          delete[] wBitmapFileName;
  24.  
  25.          UINT uFlags = gpImage->GetFlags();
  26.  
  27.          PixelFormat pf = gpImage->GetPixelFormat();
  28.  
  29.          //UINT uPropsSize, uPropsCount;
  30.          //gpImage->GetPropertySize(&uPropsSize, &uPropsCount);
  31.  
  32.          //PropertyItem* pProps = (PropertyItem*)new BYTE[uPropsSize];
  33.          //gpImage->GetAllPropertyItems(uPropsSize, uPropsCount, pProps);
  34.  
  35.          //delete[] pProps;
  36.  
  37.          int cx, cy;
  38.          Rect ImageRect(Point(0, 0), Size((cx = gpImage->GetWidth()), (cy = gpImage->GetHeight())));
  39.  
  40.          BitmapData bmData;
  41.          ZeroMemory(&bmData, sizeof(BitmapData));
  42.  
  43.         Invalidate();


но этого мало, вроде как нужен и обработчик WM_PAINT
Code:
  1. void CForSeventyDlg::OnPaint()
  2. {
  3.          if (IsIconic())
  4.          {
  5.                  CPaintDC dc(this); // device context for painting
  6.  
  7.                  SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
  8.  
  9.                  // Center icon in client rectangle
  10.                  int cxIcon = GetSystemMetrics(SM_CXICON);
  11.                  int cyIcon = GetSystemMetrics(SM_CYICON);
  12.                  CRect rect;
  13.                  GetClientRect(&rect);
  14.                  int x = (rect.Width() - cxIcon + 1) / 2;
  15.                  int y = (rect.Height() - cyIcon + 1) / 2;
  16.  
  17.                  // Draw the icon
  18.                  dc.DrawIcon(x, y, m_hIcon);
  19.          }
  20.          else
  21.          {
  22.                  CDialog::OnPaint();
  23.  
  24.                  if(gpImage)
  25.                  {
  26.                         PAINTSTRUCT ps;
  27.                         RECT rc;
  28.                         ::GetClientRect(Picture.m_hWnd, &rc);
  29.                         HDC hdc = ::BeginPaint(Picture.m_hWnd, &ps);
  30.                         Graphics *pGraphics = Graphics::FromHDC(hdc);
  31.                         int cx = gpImage->GetWidth(), cy = gpImage->GetHeight();
  32.                         pGraphics->DrawImage(gpImage, 0, 0, cx, cy);
  33.                         ::EndPaint(Picture.m_hWnd, &ps);
  34.               }
  35.          }
  36. }


Использован gdi+. Проверил только сейчас - код рабочий. Уже не понмю, что там ещё написано, и для чего так, не хочу разбираться...

Для простоты было налеплено всё в классе диалогового окна:
Code:
  1. class CForSeventyDlg : public CDialog
  2. {
  3. // Construction
  4.          Bitmap* gpImage, **pSymbols;
  5.  
  6. public:
  7.          CForSeventyDlg(CWnd* pParent = NULL); // standard constructor
  8.  
  9. // Dialog Data
  10.          enum { IDD = IDD_FORSEVENTY_DIALOG };
  11.  
  12.          protected:
  13.          virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
  14.  
  15.  
  16. // Implementation
  17. protected:
  18.          HICON m_hIcon;
  19.  
  20.          // Generated message map functions
  21.          virtual BOOL OnInitDialog();
  22.          afx_msg void OnPaint();
  23.          afx_msg HCURSOR OnQueryDragIcon();
  24.          DECLARE_MESSAGE_MAP()
  25. public:
  26.          CStatic Picture;
  27.          CListBox BitmapList;
  28.          bool VerifyImageOnLabel(char* ImageFileName, char* Label);
  29.          afx_msg void OnLbnSelchangeList1();
  30.          CEdit edLabel;
  31.          afx_msg void OnBnClickedButton1();
  32.          afx_msg void OnBnClickedButton2();
  33.          void CALLBACK LineDDAProc(int x, int y, LPARAM lpData);
  34.          CStatic Symbol1;
  35.          CStatic Symbol2;
  36.          CStatic Symbol3;
  37.          CStatic Symbol4;
  38.          CStatic Symbol5;
  39.          CStatic Symbol6;
  40. };


-----
IZ.RU


| Сообщение посчитали полезным: ELF_7719116

Ранг: 431.7 (мудрец), 390thx
Активность: 0.730.32
Статус: Участник

Создано: 26 декабря 2015 00:04 · Поправил: dosprog
· Личное сообщение · #3

ELF_7719116 пишет:
Да ни фига не отрисовывает в окне - хотя вроде всё ок должно быть!


Отрисовывается нормально. Только я не заметил какой-либо зависимости от параметра <cTransparentColor>.
Надо разбираться, что там за битоверчение.

--> Тут рабочий пример <-- (Pass: exelab)

| Сообщение посчитали полезным: ELF_7719116


Ранг: 52.0 (постоянный), 146thx
Активность: 0.030.08
Статус: Участник

Создано: 26 декабря 2015 07:57 · Поправил: UniSoft
· Личное сообщение · #4

может проще задействовать соответствующую API из msimg32.dll?
TransparentBlt()
или сразу GdiTransparentBlt() из gdi32.dll

http://rsdn.ru/archive/vc/issues/pvc045.htm

---
dosprog пишет:
Если есть способ обойтись без этого, то лучше обойтись без этого.

А смысл изобретать велосипед?
ну не нравится msimg32.dll, тогда можно вызывать сразу напрямую GdiTransparentBlt() из gdi32.dll,
если не требуется поддержка Win98

| Сообщение посчитали полезным: ELF_7719116

Ранг: 431.7 (мудрец), 390thx
Активность: 0.730.32
Статус: Участник

Создано: 26 декабря 2015 12:54 · Поправил: dosprog
· Личное сообщение · #5

UniSoft пишет:
может проще задействовать соответствующую API из msimg32.dll?


Если есть способ обойтись без этого, то лучше обойтись без этого.
Если есть способ





Ранг: 419.0 (мудрец), 647thx
Активность: 0.460.51
Статус: Участник
"Тибериумный реверсинг"

Создано: 27 декабря 2015 19:11
· Личное сообщение · #6

Получилось вообщем!
dosprog пишет:
Отрисовывается нормально. Только я не заметил какой-либо зависимости от параметра <cTransparentColor>.

Почему, он отвечает за цвет, который не будет отрисовываться, тем самым обеспечивая прозрачность. Вот тут некие подробности: http://www.sources.ru/msdn/howto/q79212.shtml

UniSoft пишет:
TransparentBlt()

Тоже, как варианТ!

Есть ещё вариант с расширением PNG - прозрачность черезе альфа-канал



Ранг: 431.7 (мудрец), 390thx
Активность: 0.730.32
Статус: Участник

Создано: 27 декабря 2015 20:21 · Поправил: dosprog
· Личное сообщение · #7

ELF_7719116 пишет:
Почему, он отвечает за цвет, который не будет отрисовываться, тем самым обеспечивая прозрачность.


А, ну да. То я просто слишком сложные маски задавал для сложных картинок.
Пример, тот, что выше, работает - можно маску задать не FFffFFh, а 0 - тогда всё очевидно.




 eXeL@B —› Вопросы новичков —› Дэбильный вопрос по програмированию
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати