Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Результат SelectObject  [new]
Машенька, 9 лет
Guest
Всем добренького времени суточек.
Я хочу создать битмапик и порисовать в нем.
Для этого создаю контекстик CreateCompatibleDC() и сам битмапик CreateCompatibleBitmap().
Создаю кисточку CreateSolidBrush() и карандашик CreatePen().
Выбираю в контекстик битмапик, кисточку и карандашик SelectObject().
Рисую прямоугольничек Rectangle() и кружочек Ellipse().
Свои кисточки и карандашики я удаляю DeleteObject().
А вот что в итоге делать с результатами SelectObject()?
Нужно ли их сохранять, а потом возвращать на место в контекстик перед удалением контекстика DeleteDC()?
Тоже самое и с битмапиком...
22 мар 12, 09:11    [12292740]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
srf2000
Member

Откуда: Новосибирск
Сообщений: 2431
Машенька, Pen - это не карандашик, а ручечка или перышко
22 мар 12, 09:23    [12292767]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
FlyD
Member

Откуда: Москва
Сообщений: 3899
Машенька, посмотреть в msdn-чик: SelectObject
Примерчик использования
22 мар 12, 09:38    [12292812]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
Машенька, 9 лет
Guest
Меня путает то, что в примерчике контекстик получается через BeginPaint(), я же его создаю сама.
Получается, что в новом контекстике уже есть какие-то кисточки и карандашики? Ой, извините, перышки.
А битмапик надо тоже запоминать и возвращать?
22 мар 12, 09:47    [12292849]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
roschinspb
Member

Откуда: С-Пб
Сообщений: 1632
SelectObject() возвращает тот графический объектик, который был раньше выбран, в начале рисования это будет умолчательная кисточка, карандашик, шрифтик и т.п. Перед тем как удалить свой объектик, надо обязательно выбрать для контекста другой объектик, возможно тот, что был выбран до начала рисования.
Если попытаться удалить объект, который в данный момент выбран для контекста, то он не удалится (достаточно посмотреть на результат функции DeleteObject, кстати вообще не вредно смотреть на результаты выполнения функций API), и будет маленькая утечечка ресурсиков, т.е. рано, или поздно кисточки и карандашики кончатся и программа завалится в сраное говно вместо рисования картинок, будет показывать окошки со страшными иностранными словами.
22 мар 12, 10:59    [12293338]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
Машенька, 9 лет
Guest
Я теперь все правильно сделала?
program Project1;

{$APPTYPE CONSOLE}

uses
  ActiveX, Windows;

function OleSavePictureFile(dispPicture: IDispatch;
  bstrFileName: TBStr): HResult; stdcall; external 'oleaut32.dll';

procedure SaveBitmap(hBitmap: HBITMAP; hPalette: HPALETTE;
  const FileName: String);
var
  pDesc: PICTDESC;
  pPicture: IPicture;
begin
  ZeroMemory(@pDesc, SizeOf(PICTDESC));
  pDesc.cbSizeofstruct:=SizeOf(PICTDESC);
  pDesc.picType:=PICTYPE_BITMAP;
  pDesc.hbitmap:=hBitmap;
  pDesc.hpal:=hPalette;
  OleCreatePictureIndirect(pDesc, IPicture, True, pPicture);
  OleSavePictureFile(IDispatch(pPicture), PWideChar(WideString(FileName)));
end;

var
  ScreenDC, DC: HDC;
  Bitmap: HBITMAP;
  OldBitmap: HGDIOBJ;
  OldBrush: HBRUSH;
  OldPen: HPEN;

begin
  OleInitialize(nil);

  ScreenDC:=GetDC(0);
  DC:=CreateCompatibleDC(ScreenDC);
  Bitmap:=CreateCompatibleBitmap(ScreenDC, 500, 500);
  OldBitmap:=SelectObject(DC, Bitmap);

  Rectangle(DC, 0, 0, 500, 500);

  OldBrush:=SelectObject(DC, CreateHatchBrush(HS_DIAGCROSS, $ff0000));
  OldPen:=SelectObject(DC, CreatePen(PS_DASH, 4, $ff));

  Ellipse(DC, 100, 100, 400, 400);

  DeleteObject(SelectObject(DC, OldPen));
  DeleteObject(SelectObject(DC, OldBrush));

  SaveBitmap(Bitmap, 0, 'Project1.bmp');

  SelectObject(DC, OldBitmap);
  DeleteObject(Bitmap);
  DeleteDC(DC);
  ReleaseDC(0, ScreenDC);
end.
22 мар 12, 11:58    [12293862]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
roschinspb
Member

Откуда: С-Пб
Сообщений: 1632
Машенька, 9 лет, я бы вот так DeleteObject(SelectObject(DC, OldPen)); не делал. В данном случае ошибок нет, но если между Select и Delete будет выбран еще один Pen (может быть позденее), то ты удалишь совсем не то, что хотела. Лучше сразу делать приблизительно так
NewPen := CreatePen(PS_DASH, 4, $ff);
if NewPen <> 0 then
begin
  OldPen:=SelectObject(DC, NewPen);
  try
    Ellipse(DC, 100, 100, 400, 400);
  finally
    SelectObject(DC, OldPen)
    DeleteObject(NewPen);
  end;
end;
22 мар 12, 12:16    [12294022]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
Машенька, 9 лет
Guest
а можно при выборе новой кисточки всегда удалять текущую DeleteObject(SelectObject(DC, NewBrush)); ?
или при удалении контекстика DeleteDC(DC); важно, чтобы была выбрана оригинальная кисточка?
ведь системочка в результатике может удалить мою последнюю - ей может все-равно какую удалять?
и почему когда я делаю Bitmap:=CreateCompatibleBitmap(DC, 500, 500);
вместо Bitmap:=CreateCompatibleBitmap(ScreenDC, 500, 500); то битмапик получается 1bppx,
ведь DC:=CreateCompatibleDC(ScreenDC); ?
23 мар 12, 10:31    [12300036]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
Соколинский Борис
Member

Откуда: Москва
Сообщений: 10824
Машенька, 9 лет
и почему когда я делаю Bitmap:=CreateCompatibleBitmap(DC, 500, 500);
вместо Bitmap:=CreateCompatibleBitmap(ScreenDC, 500, 500); то битмапик получается 1bppx,
ведь DC:=CreateCompatibleDC(ScreenDC); ?
Справочку почитать не пробовала?
оттуда
Because memory device contexts allow both color and monochrome bitmaps, the format of the bitmap returned by the CreateCompatibleBitmap function differs when the specified device context is a memory device context. However, a compatible bitmap that was created for a nonmemory device context always possesses the same color format and uses the same color palette as the specified device context.
23 мар 12, 11:02    [12300286]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
AWSVladimir
Member

Откуда:
Сообщений: 868
Машенька обязательно пользоваться апи?
Будь проще и люди к тебе потянутся.


var
bmp:TBitmap;
begin
bmp:=TBitmap.Create;
bmp.pixelFormat:=pf24bit;
bmp.SetSize(500,500);
bmp.Canvas.brush.color:=clRed;
bmp.Canvas.FillRect(Rect(200,200,400,400));
bmp.SaveToFile(Application.exename+'.bmp');
bmp.free;
end;
23 мар 12, 13:31    [12301575]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
Gator
Member

Откуда: Москва
Сообщений: 14978
AWSVladimir, будь прилежней, и люди к тебе прислушаются. :)
Когда научишься жмакать SRC и Просмотр ?
23 мар 12, 18:58    [12304197]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
S.G.
Member

Откуда: cartoon network
Сообщений: 30613
Gator, +1

AWSVladimir
Машенька обязательно пользоваться апи?
var 
 bmp:TBitmap;
begin
...
AWSVladimir, здесь, чтобы бьть в соответствующем стиле, надо как минимум нечто такое:
type 
  TBitmapic = TBitmap;
var 
 bitmapic:TBitmapic;
begin
...
ну и далее в том же духе.

;)
23 мар 12, 20:54    [12304627]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
Makar4ik
Member

Откуда: Когда-то были Лужки, а теперь Бордюр-Сити.
Сообщений: 2677
Машенька, 9 лет
а можно при выборе новой кисточки всегда удалять текущую DeleteObject(SelectObject(DC, NewBrush)); ?
или при удалении контекстика DeleteDC(DC); важно, чтобы была выбрана оригинальная кисточка?
ведь системочка в результатике может удалить мою последнюю - ей может все-равно какую удалять?
и почему когда я делаю Bitmap:=CreateCompatibleBitmap(DC, 500, 500);
вместо Bitmap:=CreateCompatibleBitmap(ScreenDC, 500, 500); то битмапик получается 1bppx,
ведь DC:=CreateCompatibleDC(ScreenDC); ?
А почему бы не удалять поименованную кисточку DeleteObject(NewBrush);, а потом говорить SelectObject(DC, OldBrush);
Вопросик, как я понял, тогда отпадёт сам по себе...
Лишняя строчечка в программке не сильно усложнит сгенерированный компайлером кодик, но при этом, будет точная гарантия того, что на всех версиях windows этот кусочек кода работает идентично.
23 мар 12, 22:34    [12304915]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
Машенька, 9 лет
Guest
Тогда, наверное, нужно сначала выбрать оригинальную кисточку SelectObject(DC, OldBrush), а потом удалить свою DeleteObject(NewBrush)?
26 мар 12, 12:38    [12313600]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
Makar4ik
Member

Откуда: Когда-то были Лужки, а теперь Бордюр-Сити.
Сообщений: 2677
Машенька, 9 лет
Тогда, наверное, нужно сначала выбрать оригинальную кисточку SelectObject(DC, OldBrush), а потом удалить свою DeleteObject(NewBrush)?
Машенька.
Вы и так её уже выбираете.

Вы же сами писали в своём кодике:
OldBrush:=SelectObject(DC, CreateHatchBrush(HS_DIAGCROSS, $ff0000));
27 мар 12, 04:32    [12317975]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
Makar4ik
Member

Откуда: Когда-то были Лужки, а теперь Бордюр-Сити.
Сообщений: 2677
ой, да простите, не понял вопроса сперва.

Конечно.

по идее, лучше выбрать старую, а потом удалить ненужную.
Конечно.
27 мар 12, 04:35    [12317977]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
Makar4ik
Member

Откуда: Когда-то были Лужки, а теперь Бордюр-Сити.
Сообщений: 2677
хотя...
пока программка не обращается к несуществующему дескриптору, то ей глубоко пофиг, живой он, или мёртвый.


Так что, по большому счёту, и программисту, и программе - глубоко фиолетово, в каком порядке убивать и вспоминать...

Но... Только ради внутренней дисциплины программиста - ЭТО есть хорошее решение.
Сначала вспомнить предыдущее, а потом убить старое(новое).
27 мар 12, 04:40    [12317980]     Ответить | Цитировать Сообщить модератору
 Re: Результат SelectObject  [new]
Makar4ik
Member

Откуда: Когда-то были Лужки, а теперь Бордюр-Сити.
Сообщений: 2677
...под "внутренней дисциплиной" - я подразумеваю попытки разработки многопоточных приложений, пользующихся едиными дескрипторами.

Но по любому, это путь очень сложный. Надо синхронизировать. Это тяжко.
И первый (но далеко не последний) шаг к этому - как раз такой:
Менять на старый, и только потом убивать новый.

Вы правы, Машенька. Надо сразу привыкать к правильной последовательности команд.

Если в одном потоке прокатит что угодно, то в многопоточном приложении - надо думать намного "длиннее".
И если вы пока так не пишете - то кто знает...???
Возможно, через 157.7 миллиардов микросекунд - вы захотите рисовать многопоточные приложения с графикой...
27 мар 12, 04:55    [12317990]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить