Конференция "WinAPI" » Проверить на существование HGDIOBJ [D7, Win2k]
 
  • Громовержец (05.01.16 23:07) [0]
    у меня есть некие HGDIOBJ объекты. по идее вопрос для всех подтипов, но конкретно сейчас вожусь с HBITMAP. как мне проверить существует ли этот объект?
    думал GetObjectType выдаст ошибку, если объект не существует - оказалост фиг, возвращает верную константу.
    ковыряюсь в MSDN, но пока не нахожу нужного. попытаться что ли GetObject вызвать? но мне же для любого типа надо и просто узнать не был ли он уже удалён.
  • Громовержец (05.01.16 23:19) [1]
    немного поясню - объекту делается DeleteObject. по идее он после этого больше не существует:

    >> После того, как объект удаляется, его дескриптор более не допустим.

    ну и вот как же имея только дескриптор узнать допустим он в данный момент или уже нет?
  • Rouse_ © (06.01.16 01:33) [2]
    Никак, технически он валиден всегда
  • Rouse_ © (06.01.16 01:37) [3]
    Вот тут гдето в каментах я описание давал: http://alexander-bagel.blogspot.ru/2013/12/2_23.html
  • Громовержец (06.01.16 03:06) [4]
    не ведал я об блоге сиём, дюже любопытно в ём...

    то есть я сделал DeleteObject(HBITMAP), но он остался валиден? во дела... дак может тогда их можно вовсе не удалять никогда? или можно по пять раз подряд "удалять" и это не будет ошибкой?
    тогда такой вопрос - сделал я DeleteObject(HDC), а в нём был HBITMAP выбран - он удалился? выходит не проверить это? так надо или не надо делать DeleteObject для такого битмапа? в MSDN как-то размыто написано.

    и ещё Вам в коллекцию, вдруг не встречали этот финт (D7, Win7):

    procedure TForm1.Button1Click(Sender: TObject);
    begin
    Repaint;
    DrawCaption(Handle, Canvas.Handle, Rect(10, 10, 800, 40), DC_ACTIVE Or DC_TEXT Or DC_ICON Or DC_GRADIENT);
    end;

    procedure TForm1.Button2Click(Sender: TObject);
    begin
    Repaint;
    Canvas.Lock;
    DrawCaption(Handle, Canvas.Handle, Rect(10, 50, 800, 80), DC_ACTIVE Or DC_TEXT Or DC_ICON Or DC_GRADIENT);
    Canvas.Unlock;
    end;

    procedure TForm1.Button3Click(Sender: TObject);
    var dc: HDC;
    begin
    Repaint;
    dc:=GetDC(Handle);
    DrawCaption(Handle, dc, Rect(10, 90, 800, 120), DC_ACTIVE Or DC_TEXT Or DC_ICON Or DC_GRADIENT);
    ReleaseDC(Handle, dc);
    end;

  • Rouse_ © (06.01.16 11:49) [5]
    Нет, удалять нужно - обязательно (ибо счетчик), но т.к. это глобальная вещь то ее можно нехитрым образом и оживить.

    По поводу кода - пока лениво смотреть, после новогодних гляну что там такое.
  • Rouse_ © (06.01.16 17:57) [6]
    Посмотрел, ну в принципе нюанс красивый, причину сможешь понять если посмотришь к какому DC привязан первый вызов
  • Лори (06.01.16 20:44) [7]
    Может DrawCaption это типа макроса или обёртки? Просто вызывает TextOut, GradientFill и прочее? А между ними DC успевает разрушиться как описано по ссылке?

    > сделал я DeleteObject(HDC), а в нём был HBITMAP выбран - он удалился?

    гм... А в доках вовсе не написано чтоб DeleteObject принимал контекст. Может вы спутали с DeleteDC?
    Зато написано что освобождаются все системные ресурсы связанные с удаляемым объектом. Так что если битмап был в DC - возможно что не нужно удалять. Но явно не написано.

    > (ибо счетчик)

    Просто любопытно - а до этого счётчика добраться возможно? Посмотреть какое там значение? И если ноль - то дескриптор таки точно не валиден. =)
  • Rouse_ © (06.01.16 21:11) [8]
    Да, конечно возможно, любой хэндл это указатель на структуру
  • Лори (06.01.16 22:28) [9]
    Поковырял ещё этот MSDN, короче вообще нельзя DeleteObject(HDC) делать. Раз "технически он валиден всегда" - то не проверишь удаляется ли он той функцией или нет, но документация указывает что надо делать только через DeleteDC(HDC).
    А вот удаляются ли всякие перья, кисти, шрифты, битмапы, регионы, палитры - которые были в удаляемом HDC - чтот не нашёл.

    > если посмотришь к какому DC привязан первый вызов

    гм... Сейчас перечитал это ещё два раза и понял что не понял что именно подразумевалось... "Привязан" это что? Как это "смотреть"? Поясните?

    > Да, конечно возможно, любой хэндл это указатель на структуру

    ммм) А примерчика под рукой не завалялось случайно?
  • Rouse_ © (06.01.16 22:37) [10]
    Начни с этого: http://rouse.drkb.ru/books.php#fen_juan
  • Rouse_ © (06.01.16 22:43) [11]
    Вот еще по структуре: http://code.reactos.org/browse/reactos/trunk/reactos/include/user32/dce.h?r=813
    Там не совсем полно, но суть отображает
  • Игорь Шевченко © (07.01.16 10:45) [12]
    Громовержец   (05.01.16 23:07)  

    Программу нормально писать не предлагать ? До чего только народ не доходит в своих попытках гланды вырезать.
  • Громовержец (08.01.16 13:57) [13]
    ой, ой. точно, спасибо!

    почему? есть же функция IsWindow() и ею пользуются. и это нормально и правильно. почему вам кажется странным моё ожидание такой же только для HGDIOBJ?
  • Игорь Шевченко © (08.01.16 23:52) [14]
    Громовержец   (08.01.16 13:57) [13]

    По одной простой причине - окна доступны всем, а объекты GDI - только процессу-владельцу (не считая стоковых, которые тоже доступны всем).
    Рекомендую почитать:
    https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms724291(v=vs.85).aspx
  • Dimka Maslov © (12.01.16 15:42) [15]
    Если хандлы создаются в процессе работы функции рисования, они там же и должны быть прибиты через DeleteObject. Если они вдруг становятся глобальными - для них существуют классы-оболочки, которые сами следят за валидностью хандла.
 
Конференция "WinAPI" » Проверить на существование HGDIOBJ [D7, Win2k]
Есть новые Нет новых   [118666   +37][b:0][p:0.001]