powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Помогите из bitmap (из Picturebox) правильный кусочек вырезать, туплю-с.
7 сообщений из 7, страница 1 из 1
Помогите из bitmap (из Picturebox) правильный кусочек вырезать, туплю-с.
    #38235895
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уж очень прозрачного тулбара хочется.

Идея явно рабочая.
Форма, на ней PictureBox, в нем картинка:
Код: vbnet
1.
2.
Private Sub Form_Load()
  PictureFon.Picture = LoadPicture("IMG_FOTO.jpg")



В PictureBox нарисован Rebar(API), в нем соотв. Toolbar (в банде).

Ну надо думать, что реальные координаты Rebar (x,y, dx, dy) я как нибудь найду -в принципе x,y, dx -заданы при его создании, плавать может чуть высота dy (разные размеры кнопок и т.п.)

В принципе чтоб бухнуть фоновую картинку в подложку, достаточно
Код: vbnet
1.
2.
3.
4.
5.
6.
  With rbBand
    .cbSize = LenB(rbBand)
    .fMask = RBBIM_BACKGROUND
    .hbmBack = Form1.PictureFon.Picture.Handle
  End With
  SendMessage g_hwndRebar, RB_SETBANDINFOA, 0, rbBand


ну или с IPictureDisplay

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
  Set g_picRebarBackground = CreateIPictureDispFromHBITMAP(Form1.PictureFon.Picture.Handle)
  
  With rbBand
    .cbSize = LenB(rbBand)
    .fMask = RBBIM_BACKGROUND
    .hbmBack = g_picRebarBackground.Handle
  End With
  SendMessage g_hwndRebar, RB_SETBANDINFOA, 0, rbBand



Но это будет вся картинка, "взятая сверху"
Но мне вся картинка не нужна, а нужен только кусочек под ребаром, с пикселями потом поиграюсь.
Я подобную задачу решал для всяких ListView, но там я игрался с hdc, с CreateCompatibleBrush и т.п.
Здесь вроде как чистая статика и все еще проще.
Но я не понимаю как сделать этот маленький bitmap из большого, потом его видимо засунуть в IpictureDisplay (с этим вроде ясно).
...
Рейтинг: 0 / 0
Помогите из bitmap (из Picturebox) правильный кусочек вырезать, туплю-с.
    #38237295
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хорошо, поставим вопрос по другому.
Форма в пикселях,
на ней 2 picturebox-а -тоже в пикселях.
1) PictureFon
2) PictureCopy
Код: vbnet
1.
2.
Private Sub Form_Load()
  PictureFon.Picture = LoadPicture("IMG_FOTO.jpg")



Мне нужен кусок картинки PictureFon
Я знаю x,y, dx, dy куска кот. мне нужен
Как мне отобразить этот кусок на PictureCopy

Я пытаюсь сделать что-то типа:

Код: vbnet
1.
  PictureFon.Picture.Render PictureCopy.hdc, 0, 0, 200, 200, 0, 0, 200, 200, ByVal 0&



По моим соображениям у меня должен скопироваться верхний левый кусок 200х200px
У меня там фигня из черно-серых квадратов рисуется.
Я эти координатные преобразования понять не могу, я нарочно везде сделал px, чтоб не связываться с делением-умножением на 15. Оно явно берет не тот кусок и не в том масштабе.

Это не по API вопрос, а по чистому VB6.
...
Рейтинг: 0 / 0
Помогите из bitmap (из Picturebox) правильный кусочек вырезать, туплю-с.
    #38238117
Фотография Бенедикт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

по Render: он ожидает координаты в исходном изображении в himetric units - сотых долях мм (т. е. в тех же единицах измерения, в которых идёт Width и Height). Кроме того, DIB-ы, формируемые LoadPicture() для JPEG-ов (да и вообще большинство на практике попадающихся DIB-ов), имеют порядок следования скан-линий снизу вверх (bottom up), из-за чего для Render надо указывать для исходного куска нижнюю скан-линию и отрицательную высоту:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
 '...
 hbmMono32 = CreateDIBSection(0, bmiMono32, DIB_RGB_COLORS, pbitMono32, 0, 0)
 SelectObject hdcDst, hbmMono32
 
 Dim picSrc As IPictureDisp
 Set picSrc = LoadPicture("C:\mmm.jpg")
 Dim cxSrc As Long, cySrc As Long
 cxSrc = Int(bmiMono32.bmiHeader.bV5Width * Screen.TwipsPerPixelX * 2540 / _
             1440 + 0.5) 'пересчёт pixel->himetric
 cySrc = Int(bmiMono32.bmiHeader.bV5Height * Screen.TwipsPerPixelY * 2540 / _
             1440 + 0.5) 'пересчёт pixel->himetric
 picSrc.Render CLng(hdcDst), 0&, 0&, CLng(bmiMono32.bmiHeader.bV5Width), _
               CLng(bmiMono32.bmiHeader.bV5Height), 0&, _
               CLng(picSrc.Height), CLng(cxSrc), CLng(-cySrc), ByVal 0&
...
Рейтинг: 0 / 0
Помогите из bitmap (из Picturebox) правильный кусочек вырезать, туплю-с.
    #38238887
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бенедикт,

мне этот render что-то сразу не понравился.
Я сделал по другому, типа гибрид из своего приема с CreatePatternBrush и твоего CreateIPictureDispFromHBITMAP (тест-проект во вложении):
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
Public Function CreateTransparentBackGround( _
 ByVal hwndRebar As Long) As IPictureDisp
  Dim rc As RECT
  Dim tPt As POINTAPI
  Dim hdcRef As Long
  Dim hdcDst As Long
  Dim hbmDst As Long
  Dim hbmOld As Long

  'Dim the_hdc As Long
  Dim hbmDstOld As Long
  Dim RebarHeight As Long
  Dim RebarWidth As Long
  
  Dim hbmpBack_temp As Long
  Dim hbshBack_temp As Long
  
  
  hbmpBack_temp = Form1.PictureFon.Picture.Handle
  If hbmpBack_temp <> 0 Then
    hbshBack_temp = CreatePatternBrush(hbmpBack_temp)
  Else
    'затычка на случай отсутствия фоновой картинки
    Dim the_ColorRef As Long
    OleTranslateColor vbButtonFace, 0, the_ColorRef
    hbshBack_temp = CreateSolidBrush(the_ColorRef)
  End If
  
  GetWindowRect hwndRebar, rc
  If ThemesEnabled(hwndRebar) Then
    rc.Left = rc.Left + 2
  End If
  RebarWidth = rc.Right - rc.Left
  RebarHeight = rc.Bottom - rc.Top
  
  hdcRef = GetDC(hwndRebar)
  hdcDst = CreateCompatibleDC(hdcRef)
  hbmDst = CreateCompatibleBitmap(hdcRef, RebarWidth, RebarHeight)
  ReleaseDC hwndRebar, hdcRef
  hbmOld = SelectObject(hdcDst, hbmDst)

  hbmDstOld = SelectObject(hdcDst, hbshBack_temp)
  SetBkMode hdcDst, TRANSPARENT
  tPt.x = rc.Left
  tPt.y = rc.Top
  MapWindowPoints 0, Form1.PictureFon.hwnd, tPt, 2
  rc.Left = tPt.x
  rc.Top = tPt.y
  SetBrushOrgEx hdcDst, -rc.Left, -rc.Top, tPt
  PatBlt hdcDst, 0, 0, RebarWidth, RebarHeight, PATCOPY
  SelectObject hdcDst, hbmDstOld
  
  SelectObject hdcDst, hbmOld: hbmOld = 0
  DeleteDC hdcDst: hdcDst = 0
  
  DeleteObject hbshBack_temp
 
  Set CreateTransparentBackGround = CreateIPictureDispFromHBITMAP(hbmDst)
End Function



Вроде как это работает.
Но мне чего-то эта идея с прозрачным тулбар разонравилась.

Я то хотел дать возможность пользователю выбирать между Transparent/Communication/Media и т.п.

Но чтобы сделать Transparent, надо
1) задвинуть ребар в контейнер-Picturebox на 2px -проблема проиллюстрирована здесь:
Что можно сделать с той частью Rebar которая до Band - это 2 пикселя.
2) подогнать высоту контейнера-Picturebox под высоту Rebar -после создания
3) как-то нарисовать границу этого ребар - видимо как границу PictureBox-контейнера (границ кнопок то не видно даже, если не наводить мышку, надо ж как то обозначить его)

Типа вот так
Код: vbnet
1.
2.
3.
4.
5.
  Dim rcClient As RECT
  GetClientRect hwndRebar, rcClient
  
  pvSetBorderStyle Form1.PictureRB.hwnd, eBorderStyleConstants.bsThin
  Form1.PictureRB.Height = rcClient.Bottom



И смотрится это честно говоря не так красиво, как тематический Communication/Media подобранный под фон картинки.

А если потом в этой конструкции менять стиль назад на Communication, то понимаешь что
1) eBorderStyleConstants.bsThin надо убирать, т.к. тематический рисует свою "границу"
2) задвинуть ребар в контейнер-Picturebox на 2px -срезает левую границу тематического ребар, т.к. в случае "честной темы" эти 2px составляют единое целое тематики

Короче, очень мудреные коды надо делать, отказался я от этой идеи.
...
Рейтинг: 0 / 0
Помогите из bitmap (из Picturebox) правильный кусочек вырезать, туплю-с.
    #38238932
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77А если потом в этой конструкции менять стиль назад на Communication, то понимаешь что...
Хотя конечно при смене стиля можно всю конструкцию полностью перерисовывать с учетом сказанного...
...
Рейтинг: 0 / 0
Помогите из bitmap (из Picturebox) правильный кусочек вырезать, туплю-с.
    #38239041
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бенедикт,

м.б. все таки воспользуюсь своим вариантом кода.
Не взглянешь профессионально на мою
CreateTransparentBackGround()?
Меня смущает, что слишком там много hdc-hbm, SelectObject и т.п.
Такое ощущение что больше чем нужно.
Так то она рабочая.
Но не получилось бы каких-нибудь утечек из-за неудаленных hdc-hbm и т.п.
...
Рейтинг: 0 / 0
Помогите из bitmap (из Picturebox) правильный кусочек вырезать, туплю-с.
    #38239321
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, не. Вставил в проект, вроде все отлично получилось (внешне). При смене стиля с прозрачного на тематическую всю конструкцию пересоздаю с учетом 2-х "левых" пикселей.
Но все же хотелось бы чтоб кто-то проверил этот код на предмет корректности и потенциальных утечек, я хоть и родил этот гибрид но до конца лесенки из этих SelectObject не понимаю.

Дмитрий77Я сделал по другому, типа гибрид из своего приема с CreatePatternBrush и твоего CreateIPictureDispFromHBITMAP (тест-проект во вложении):
Код: vbnet
1.
2.
3.
Public Function CreateTransparentBackGround( _
 ByVal hwndRebar As Long) As IPictureDisp
...
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Помогите из bitmap (из Picturebox) правильный кусочек вырезать, туплю-с.
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]