Q: Paint on the contents of a TImage control

Answer:

TImage provides a Canvas property that allows you to draw on the contents of the image. Changes made to the image become a permanent part of the image. If you copy the resulting image to the clipboard or save the image to a file, your changes will appear right with the image. Here is a code snippet that draws an arrow onto an image.

const TPoint Arrow1[] = { {80,105} , {106,66}, {80,87},{94,98}}; Image1->Canvas->Pen->Color = clBlue; Image1->Canvas->Pen->Width = 3; Image1->Canvas->MoveTo(Arrow1[0].x,Arrow1[0].y); Image1->Canvas->LineTo(Arrow1[1].x,Arrow1[1].y); Image1->Canvas->MoveTo(Arrow1[0].x,Arrow1[0].y); Image1->Canvas->LineTo(Arrow1[2].x,Arrow1[2].y); Image1->Canvas->MoveTo(Arrow1[0].x,Arrow1[0].y); Image1->Canvas->LineTo(Arrow1[3].x,Arrow1[3].y);

Note: You can only draw on the Canvas property of TImage if the Picture is empty or contains a bitmap as its graphic. You cannot draw on the Canvas of TImage if the image contains an icon or a metafile as its graphic. The GetCanvas read method of TImage demonstrates why.

// function converted to C++TCanvas * TImage::GetCanvas(){ Graphics::TBitmap *Bitmap; if (Picture->Graphic == NULL) { Bitmap = new Graphics::TBitmap Bitmap->Width = Width; Bitmap->Height = Height; // assign new bitmap to the Graphic property. This calls the // SetGraphic write method of TPicture. SetGraphic calls Assign, // equivalent to calling Picture->Graphic->Assign(Bitmap); Picture->Graphic = Bitmap; // Delete the temp bitmap pointer. Because Assign was called, // the contents of the HBITMAP is retained in Picture->Graphic delete Bitmap; } if (/* Picture->Graphic is a TBitmap object */ ) return Picture->Bitmap->Canvas; else throw EInvalidOperation( /* some args here maybe */);}

Notice that if the Picture property is empty, a new bitmap object is created for you to draw in. If a bitmap is loaded, then TImage::GetCanvas simply returns the Canvas of the Bitmap. The code generates an exception if the Picture is an icon or a metafile.

Note: As a result of how TImage::GetCanvas works, there is no difference beteen Image->Canvas and Image->Picture->Bitmap->Canvas.

Note: The width and the height of an Image control's drawing canvas are identical to the original bitmap size. This may differ from the Width and Height of the image if the bitmap has been stretched. For example, place an Image control onto a new form. Size the form so it is 500 x 400 pixels. Set the Align property of the Image control to alClient, and load in the CHEMICAL.BMP splash screen that ships with BCB. Finally, change the Stretch property to true to make the picture expand to fit the entire form. At this point, Image1->Width will equal Form1->ClientWidth, but Image1->Picture->Width will be the width of CHEMICAL.BMP (240).

Note: When you draw on an image, try to use only the standard Windows colors or a color that is already conained in the palette of the Image.

Q: Create a TCanvas object for the entire screen (or any other window).   Answer: The GetDC API function allows you to create a device context for any window. You can then assign this device context to the Handle property of a newly created TCanvas object. HDC dc = GetDC(0);Graphics::TCanvas *ScreenCanvas = new Graphics::TCanvas;ScreenCanvas->Handle = dc;ScreenCanvas->Pen->Width = 10;ScreenCanvas->Pen->Color = clRed;ScreenCanvas->MoveTo(0,0);ScreenCanvas->LineTo(Screen->Width,Screen->Height);delete ScreenCanvas;ReleaseDC(NULL,dc); You can draw on a specific window by obtaining the window handle and then passing that handle to the GetDC call. This code draws directly onto the Object Inspector if its open. HWND OIHandle = FindWindow(NULL,"Object Inspector");if(OIHandle){ HDC dc = GetWindowDC(OIHandle); Graphics::TCanvas *OICanvas = new Graphics::TCanvas; OICanvas->Handle = dc; OICanvas->Pen->Width = 10; OICanvas->Pen->Color = clRed; OICanvas->MoveTo(0,0); OICanvas->LineTo(OICanvas->ClipRect.Right,OICanvas->ClipRect.Bottom); delete OICanvas; ReleaseDC(OIHandle,dc);} Note: Use this code with caution. It works fine, but drawing directly onto another window is something that most programs should avoid.   Note: You must remember to call ReleaseDC for the HDC handle. TCanvas does not release the device context when you delete the TCanvas pointer. You can inspect TCanvas::Destroy to prove this for yourself. (So what about TForm? Does it call ReleaseDC for the HDC that was used to create its Canvas property? No. TForm uses a descendent of TCanvas called TControlCanvas. TControlCanvas automatically calls ReleaseDC in its destructor. TGraphicControl also uses TControlCanvas (look in TGraphicControl::Create)).
 

Посмотрев на WinAmp многие тоже хотят сделать такой трюк: убрать из Task Bar кнопочку своего приложения - нет ничего проще: ShowWindow(Application->Handle, SW_HIDE); Как и где это применять? Создайте проект , поместите на форму две кнопки ("Show", "Hide"), создайте для них два обработчика OnClick и примените функцию ShowWindow. Вот исходник:

//---------------------------------------------------------------------------#include #pragma hdrstop #include "Unit1.h"#include "Unit2.h"//---------------------------------------------------------------------------#pragma package(smart_init)#pragma resource "*.dfm"TForm1 *Form1;//---------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner){}//--------------------------------------------------------------------------- //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender){ ShowWindow(Application->Handle, SW_SHOW); }//---------------------------------------------------------------------------void __fastcall TForm1::Button2Click(TObject *Sender){ ShowWindow(Application->Handle, SW_HIDE);}//---------------------------------------------------------------------------

|Создание DLL

Сейчас мы рассмотрим для чего нужны DLL (Dynamic Link Library - динамически компонуема библиотека) и как их создавать. DLL- это участок кода хранимый в файле с расширением .dll. Код может быть использован другими программами, но сама по себе библиотека прораммой не является. Вобщем-то, динамически компонуемые библиотеки представляют собой набор скомпилированных функций. Но у этих библиотек есть свой особенности, так например, если какие-то две или более программы для Windows одновременно исполняются и используют функции, находящиеся в одной DLL, то в памяти будет постоянно находится только одна библиотека, обеспечивая тем самым экономное расходование памяти. Загрузка библиотеки в память может быть статической и динамической.

При статической загрузке DLL автоматически загружается при запуске исользующего ее приложения. Такая DLL содержит экспортируемые функции, описание которых находится в файле библиотеки импорта(import library file - .lib). Для использования статической загрузки вы должны на этапе компоновки к программе додключить .lib файл вашей DLL. В C++ Builder это сводится к включения в проект .lib файла через менджер проектов.

При диамической загрузке вы можете загружать DLL при необходимости, выгрузить ее когода она ненужна. Однако работать с такими библиотеками сложнее чем со статическими. Рассмотрим созздание и использование DLL статической загрузки.

Наши рекомендации