powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / При создании hBitmap и IPictureDisp из него что я должен удалять при выгрузке формы
8 сообщений из 8, страница 1 из 1
При создании hBitmap и IPictureDisp из него что я должен удалять при выгрузке формы
    #38230168
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Т.е.
Код: 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.
Public Function CreateGradientBack( ...) As IPictureDisp
...
 hdcRef = GetDC(hwndRef)
 hdcDst = CreateCompatibleDC(hdcRef)
 hbmDst = CreateCompatibleBitmap(hdcRef, b * s, u * 2 + 1)
 hbmOld = SelectObject(hdcDst, hbmDst)
 GradientFill hdcDst, v0(0), 2 * (b + 1), t(0), b * 2, GRADIENT_FILL_TRIANGLE
 GradientFill hdcDst, v1(0), 2 * (b + 1), t(0), b * 2, GRADIENT_FILL_TRIANGLE
 GradientFill hdcDst, v2(0), 2 * (b + 1), t(0), b * 2, GRADIENT_FILL_TRIANGLE
 SelectObject hdcDst, hbmOld: hbmOld = 0
 DeleteDC hdcDst: hdcDst = 0
 
 Set CreateGradientBack = CreateIPictureDispFromHBITMAP(hbmDst)
 'DeleteObject hbmDst: hbmDst = 0
End Function

Public Function CreateIPictureDispFromHBITMAP( _
   ByVal hBitmap As Long, _
   Optional ByVal hPal As Long = 0, _
   Optional ByVal fPictureOwnsHandle As Boolean = True) As IPictureDisp
 Dim IID_IDispatch As GUID
 Dim Pic As PicBmp

 With Pic
    .Size = Len(Pic)
    .Type = PICTYPE_BITMAP
    .hBmp = hBitmap
    .hPal = hPal
 End With
 With IID_IDispatch
    .Data1 = &H20400
    .Data4(0) = &HC0
    .Data4(7) = &H46
 End With
 OleCreatePictureIndirect Pic, IID_IDispatch, -fPictureOwnsHandle, _
                          CreateIPictureDispFromHBITMAP
End Function



По идее я ему должен сделать
Код: vbnet
1.
DeleteObject hbmDst: hbmDst = 0


Но если я это сделаю на этапе создания то моя
As IPictureDisp
будет бесполезна.

В коде я делаю:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
    Set g_picRebarBackground = CreateGradientBack(g_hwndToolBar, Form1.ScaleWidth, _
    With rbBand
       .cbSize = LenB(rbBand)
       .fMask = RBBIM_BACKGROUND
       .hbmBack = g_picRebarBackground.Handle
    End With
    SendMessage g_hwndRebar, RB_SETBANDINFOA, uBandCount - 1, rbBand



Варианты ответа:
1) DeleteObject g_picRebarBackground
2) DeleteObject g_picRebarBackground.Handle
3) Set g_picRebarBackground = Nothing
4) ваабще ничего не делать

Если бы g_picRebarBackground создавался один раз я бы забил.
Но при Form_resize я его перерисовываю (градиент растянут на ширину Rebar, перерисовка вполне себе культурно внешне работает):
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Private Sub Form_Resize()
...
    DeleteObject g_picRebarBackground '?????????????????
    
    Set g_picRebarBackground = CreateGradientBack(g_hwndToolBar, Form1.ScaleWidth, _
     rRB.Bottom - rRB.Top)
    Dim rbBand As REBARBANDINFO
    With rbBand
       .cbSize = LenB(rbBand)
       .fMask = RBBIM_BACKGROUND
       .hbmBack = g_picRebarBackground.Handle
    End With
    SendMessage g_hwndRebar, RB_SETBANDINFOA, 0, rbBand
    Call RedrawWindow(g_hwndToolBar, ByVal 0&, ByVal 0&, RDW_INVALIDATE Or RDW_ERASE)



Задница в том, что если я чего-то недоглядел и ресурсы эти жрутся, а не авто-удаляются (как хотелось бы), то это задница, поэтому опасения не праздные.

Да, и еще.
Если сделать
1) DeleteObject g_picRebarBackground
2) DeleteObject g_picRebarBackground.Handle
а при этом в коде не выполнялось
set = g_picRebarBackground
то прога при этом вылетит
Error91: Object NOT set

Как записать
If (g_picRebarBackground) then DeleteObject
(будем считать, я не знаю точно был ли он Set -делается в завис. от OS, от выбранного стиля и т.п., юзер мог допустим отключить Темы в процессе работы - я специально данное действо не отслеживаю -пускай перегружает если интерфейс сильно съехал)
...
Рейтинг: 0 / 0
При создании hBitmap и IPictureDisp из него что я должен удалять при выгрузке формы
    #38230174
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так застрахован?
Код: vbnet
1.
2.
3.
4.
  If Not g_picRebarBackground Is Nothing Then
    'MsgBox "Set"
    DeleteObject g_picRebarBackground.Handle
  End If
...
Рейтинг: 0 / 0
При создании hBitmap и IPictureDisp из него что я должен удалять при выгрузке формы
    #38230405
Фотография Бенедикт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

COM-объект, поддерживающий интерфейс IPictureDisp, либо сам управляет временем жизни GDI-объекта (делает DeleteObject (для битмапа)), либо не управляет вовсе. Это определяется третьим параметром OleCreatePictureIndirect(), он же третий параметр CreateIPictureDispFromHBITMAP().

Если параметр не равен FALSE/False (нулю, короче), то такие фокусы как DeleteObject g_picRebarBackground не нужны (и даже вредны), но в данном конкретном случае ни к какому фатальному эффекту не приведут. Ресурсы будут освобождены при уменьшении счётчика использования COM-объекта до нуля. В явном виде уменьшение счётчика это Set g_picRebarBackground = Nothing. В неявном - Set g_picRebarBackground = <другой объект>.

Если параметр равен FALSE, то пользователь объекта должен явно управлять временем жизни GDI-объекта.
...
Рейтинг: 0 / 0
При создании hBitmap и IPictureDisp из него что я должен удалять при выгрузке формы
    #38230415
Фотография Бенедикт
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Так застрахован?
Код: vbnet
1.
2.
3.
4.
  If Not g_picRebarBackground Is Nothing Then
    'MsgBox "Set"
    DeleteObject g_picRebarBackground.Handle
  End If

В качестве P.S.:
Это должно было бы привести к коду вида
Код: vbnet
1.
2.
3.
If Not g_picRebarBackground Is Nothing Then
   Set g_picRebarBackground = Nothing
End If

, но это тавтология, приводящая к просто
Код: vbnet
1.
Set g_picRebarBackground = Nothing
...
Рейтинг: 0 / 0
При создании hBitmap и IPictureDisp из него что я должен удалять при выгрузке формы
    #38230839
Дмит
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня как-то к утечки приводило GetDC без ReleaseDC :)
...
Рейтинг: 0 / 0
При создании hBitmap и IPictureDisp из него что я должен удалять при выгрузке формы
    #38230912
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
БенедиктДмитрий77,

COM-объект, поддерживающий интерфейс IPictureDisp, либо сам управляет временем жизни GDI-объекта (делает DeleteObject (для битмапа)), либо не управляет вовсе. Это определяется третьим параметром OleCreatePictureIndirect(), он же третий параметр CreateIPictureDispFromHBITMAP().

Вот это, да?
fOwn [in]
If TRUE, the picture object is to destroy its picture when the object is destroyed. If FALSE, the caller is responsible for destroying the picture.
А ведь я туда глядел, видимо по принципу смотрю в книгу, вижу фигу.
А вот ты разжуешь, и сразу вижу буквы, а за ними смысл.

БенедиктЕсли параметр не равен FALSE/False (нулю, короче), то такие фокусы как DeleteObject g_picRebarBackground не нужны (и даже вредны), но в данном конкретном случае ни к какому фатальному эффекту не приведут. Ресурсы будут освобождены при уменьшении счётчика использования COM-объекта до нуля. В явном виде уменьшение счётчика это Set g_picRebarBackground = Nothing. В неявном - Set g_picRebarBackground = <другой объект>.

И все-таки, четкий ответ?
Убрать вообще все эти конструкции?
Или все-таки налепить
Код: vbnet
1.
Set g_picRebarBackground = Nothing



Потому как у меня с этими конструкциями при определенных условиях возникает
Er.91 (object NOT set), хотя вроде делаю If Not g_picRebarBackground Is Nothing Then

Приведу целиком, чего навертел:

Код: 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.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
Public Function CreateTheReBar_txt(ByVal Parent As PictureBox, ByVal str_text As String, _
 FontCtr As Control, lng_Img As Long, g_picRebarBackground_txt As IPictureDisp) As Long
  'создание панели с текстом в стиле Rebar
  'FontCtr -имя контрола, в кот. хранится нужный шрифт
  Dim rcClient As RECT
  GetClientRect Parent.hWnd, rcClient

  Dim RebarStyle As Long
  RebarStyle = WS_CHILD Or WS_VISIBLE Or WS_CLIPSIBLINGS Or WS_CLIPCHILDREN Or _
   WS_BORDER Or RBS_FIXEDORDER Or CCS_NODIVIDER Or _
   CCS_NOPARENTALIGN Or CCS_TOP '
  
  Dim the_hwndRebar As Long
  
  the_hwndRebar = CreateWindowEx(WS_EX_TOOLWINDOW, _
   REBARCLASSNAME, _
   vbNullString, _
   RebarStyle, _
   0, _
   0, _
   rcClient.Right, _
   0, _
   Parent.hWnd, _
   0&, _
   App.hInstance, _
   0&)
 
  If sys_WinVista And ThemesEnabled(the_hwndRebar) Then
    Dim the_theme As String
    the_theme = Form1.GetCurrentPanelsStyle
    If the_theme = "Classic" Then
      DeactivateWindowTheme the_hwndRebar
    ElseIf the_theme = "Explorer" Then
      SetWindowTheme the_hwndRebar, StrPtr("Communications"), 0 'стиль для Висты
    Else
      SetWindowTheme the_hwndRebar, StrPtr(the_theme), 0 'стиль для Висты
    End If
  ElseIf (IsWinXP Or IsWin2003) And ThemesEnabled(the_hwndRebar) Then
    DeactivateWindowTheme the_hwndRebar
  End If
  
  Dim fnt As IFont
  Set fnt = FontCtr.Font
  SendMessage the_hwndRebar, WM_SETFONT, fnt.hFont, ByVal 0
  Set fnt = Nothing
  
  Dim rInfo As REBARINFO
  With rInfo
    .cbSize = LenB(rInfo)
    .fMask = RBIM_IMAGELIST
    .hIml = m_hImlRB_RND
  End With
  SendMessage the_hwndRebar, RB_SETBARINFO, 0, rInfo

  Dim rbBand As REBARBANDINFO
  With rbBand
    .cbSize = LenB(rbBand)
    .fMask = RBBIM_COLORS Or RBBIM_CHILDSIZE Or RBBIM_STYLE Or RBBIM_TEXT Or RBBIM_IMAGE
    .fStyle = RBBS_NOVERT
    OleTranslateColor vbWindowBackground, 0, .clrFore
    OleTranslateColor vbButtonShadow, 0, .clrBack
    .cxMinChild = 170
    If IsWinVista And ThemesEnabled(the_hwndRebar) Then
      .cyMinChild = 25
    Else
      .cyMinChild = 22
    End If
    .lpText = VarPtr(StringToMas(str_text).ByteStr(0))
    .iImage = lng_Img 'картинка на панели
  End With

  ' Insert band into rebar
  SendMessage the_hwndRebar, RB_INSERTBAND, -1, rbBand
  
  If (the_theme = "Explorer") And sys_WinVista And ThemesEnabled(the_hwndRebar) Then
    Dim rcClientRB As RECT
    GetClientRect the_hwndRebar, rcClientRB  '!!! Надо придумать что-нибудь получше
    MsgBox "before DeleteObject"
    If Not g_picRebarBackground_txt Is Nothing Then DeleteObject g_picRebarBackground_txt.Handle
    MsgBox "after DeleteObject"
    Set g_picRebarBackground_txt = CreateGradientBackComplexPlus(g_picRebarBackground_txt, Parent.ScaleWidth, _
     rcClientRB.Bottom)
    With rbBand
       .cbSize = LenB(rbBand)
       .fMask = RBBIM_BACKGROUND
       .hbmBack = g_picRebarBackground_txt.Handle
    End With
    SendMessage the_hwndRebar, RB_SETBANDINFOA, 0, rbBand
  End If
  
  CreateTheReBar_txt = the_hwndRebar
End Function



А ошибка выдается, если при загрузке формы прога считывает значение стиля "Explorer", что предполагает именно свою отрисовку битмапа поверх банда (как ты учил), а не стиль. Возникает где-то после MsgBox "after DeleteObject", пока не "додебажил".
Или я просто что-то навертел не то с передачей "объектов" в функцию?
У меня идет создание 3-х панелей подряд, + я использую перерисовку в Form_resize, где этот object переубивается (для "этого стиля"). Не уверен что там ничего не перекрещивается.

ДмитУ меня как-то к утечки приводило GetDC без ReleaseDC :)
О-о-о! Ето большая бяка. После знакомства с этой бякой я как раз и стал переживать "чтоб все убивать".
...
Рейтинг: 0 / 0
При создании hBitmap и IPictureDisp из него что я должен удалять при выгрузке формы
    #38230943
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
О, нашел ошибку у себя:
Код: vbnet
1.
2.
    Set g_picRebarBackground_txt = CreateGradientBackComplexPlus(g_picRebarBackground_txt, Parent.ScaleWidth, _
     rcClientRB.Bottom)



Надо так
Код: vbnet
1.
2.
    Set g_picRebarBackground_txt = CreateGradientBackComplexPlus(the_hwndRebar, Parent.ScaleWidth, _
     rcClientRB.Bottom)



Странно что еще в других ситуациях это работало.
Видимо пот.
Код: vbnet
1.
DeleteObject g_picRebarBackground_txt.Handle


НЕ делал
Код: vbnet
1.
Set g_picRebarBackground_txt = Nothing



Ну а hwnd здесь видимо не шибко важен.

И все-таки
Лепить
Set = nothing?

Или стереть DeleteObject g_picRebarBackground_txt.Handle повсеместно и успокоиться?
...
Рейтинг: 0 / 0
При создании hBitmap и IPictureDisp из него что я должен удалять при выгрузке формы
    #38231765
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, исходя из всего сказанного я остановился на варианте

Код: vbnet
1.
If Not g_picRebarBackground Is Nothing Then Set g_picRebarBackground = Nothing



Если я правильно понял, то можно не делать ничего и COM-объект вместе с bitmap уничтожится автоматически при выходе из программы (переменная -глобальная).
С другой стороны юзер мог запустить программу с темой, кот. использует "кухню", выбрать тему, кот. не использует этой кухни, и в этой теме сидеть еще 24 часа. А на фига эти градиенты будут жрать память все это время.

Что касается DeleteObject с учетом объяснений про 3-й параметр OleCreatePictureIndirect(), думаю что чушь полная, тем более COM-объект оно не уничтожает (как писал выше).

Ну а насчет
1) If Not ... Is Nothing
и
2) Двойной конструкции (т.е. эти две строчки идут подряд)
Код: vbnet
1.
2.
If Not g_picRebarBackground Is Nothing Then Set g_picRebarBackground = Nothing
Set g_picRebarBackground = Create...


-как то душеньке спокойней когда логика прописана, а не подразумевается.

Как-то так...
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / При создании hBitmap и IPictureDisp из него что я должен удалять при выгрузке формы
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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