How to add ALPHA to delphi TEXTOUT Tcanvas ?
나도 저 문제에 봉착 했다.
델파이가 아니고 C++ Builder 지만...
어쨋든 두 툴이 거의 동일하다시피 하기 때문에...
앞에서 거론한 문제를 풀기위해
첫번째로 TGraphicControl의 Text를 반투명 혹은 투명하게 처리하기 위한 방안이다.
저 답을 보고 싶었으나, "돈내고 가입"해야 보는 곳이었다.
어쨋든 결재는 했으니.. 한번 해보자 ㅡㅡ;;;
-----------------------------------------------------------------------------------------------------------
첫번째 답
-------------
You need to calculate font color before painting on canvas.
Canvas.Font.Color := BlendColors(clBtnFace, clWindowText, 50); function BlendColors(Color1, Color2: TColor; Opacity: Byte): TColor; var r, g, b: Byte; c1, c2: PByteArray; begin Color1 := ColorToRGB(Color1); Color2 := ColorToRGB(Color2); c1 := @Color1; c2 := @Color2; r := Trunc(c1[0] + (c2[0] - c1[0]) * Opacity / 256); g := Trunc(c1[1] + (c2[1] - c1[1]) * Opacity / 256); b := Trunc(c1[2] + (c2[2] - c1[2]) * Opacity / 256); Result := RGB(r, g, b); end;
-----------------------------------------------------------------------------------------------------------
두번째 답
------------------
There are several ways how to do this.. Here's one of them:
object Image1: TImage Left = 2 Top = 34 Width = 317 Height = 269 OnMouseDown = Image1MouseDown OnMouseMove = Image1MouseMove end object Edit1: TEdit Left = 32 Top = 0 Width = 185 Height = 21 TabOrder = 0 Text = 'Some different text' end object Label1: TLabel Left = 0 Top = 4 Width = 21 Height = 13 Caption = 'Text' end object Edit2: TEdit Left = 264 Top = 0 Width = 57 Height = 21 TabOrder = 1 Text = '127' end object Label2: TLabel Left = 232 Top = 4 Width = 27 Height = 13 Caption = 'Blend' end object Bevel1: TBevel Left = 0 Top = 32 Width = 321 Height = 273 end
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm1 = class(TForm) Image1: TImage; Edit1: TEdit; Label1: TLabel; Edit2: TEdit; Label2: TLabel; Bevel1: TBevel; procedure Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure FormCreate(Sender: TObject); procedure TranspTxt(s : string; x, y : cardinal; BorderX, BorderY : byte; transp : byte); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin with Image1, Picture.Bitmap do begin Stretch := true; Width := Image1.Width; Height := Image1.Height; PixelFormat := pf24bit; end; end; procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin with Image1.Canvas do case Button of mbLeft : MoveTo(x, y); mbRight : TranspTxt(Edit1.Text, x, y, 4, 0, StrToInt(Edit2.Text)); end; end; procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if ssLeft in Shift then begin Image1.Canvas.LineTo(x, y); end; end; procedure TForm1.TranspTxt(s : string; x, y : cardinal; BorderX, BorderY : byte; transp : byte); // transp : // 0 - no transparency // 255 - full transparency (invisible) type TLine = array [0..32767] of TRGBTriple; PLine = ^TLine; var bmp : TBitmap; l1, l2 : PLine; w, h : word; n1, n2 : single; begin bmp := TBitmap.Create; with bmp do begin PixelFormat := Image1.Picture.Bitmap.PixelFormat; with Canvas do begin with Font do begin // font params - name, size, style, color, charset etc Name := 'Courier New'; Size := 14; Style := []; Color := $0000ff; // red end; Width := TextWidth (s) + BorderX * 2; // calculate width of text frame Height := TextHeight(s) + BorderY * 2; // calculate height of text frame Pen.Width := 3; // set border width Pen.Color := $000000; // color Brush.Color := $ffffff; // background color Rectangle(ClipRect); // draw frame (background & border) Brush.Style := bsClear; TextOut(BorderX, BorderY, s); // draw text end; n1 := 1 / 255 * transp; n2 := 1 - n1; for h := 0 to Height - 1 do begin // put it on Image1.Picture.Bitmap if y + h >= Image1.Picture.Bitmap.Height then break; // bottom of the image l1 := Image1.Picture.Bitmap.ScanLine[y + h]; l2 := ScanLine[h]; for w := 0 to Width - 1 do begin if x + w > Image1.Picture.Bitmap.Width then break; // right margin of the image l1[x + w].rgbtRed := Trunc(l1[x + w].rgbtRed * n1 + l2[w].rgbtRed * n2); l1[x + w].rgbtGreen := Trunc(l1[x + w].rgbtGreen * n1 + l2[w].rgbtGreen * n2); l1[x + w].rgbtBlue := Trunc(l1[x + w].rgbtBlue * n1 + l2[w].rgbtBlue * n2); end; end; end; bmp.Free; Image1.Refresh; end; end.
-----------------------------------------------------------------------------------------------------------
세번째답--------------
Create an in-memory bitmap.
Use TextOut to write your to the bitmap
Use AlphaBlend to merge the new bitmap and your destination with your required transparency (trans, 0 to 255)
***Note: AlphaBlend does not work on all systems. The application must be running under Windows 2000 or better***
eg ...
procedure TForm1.AlphaTextOut(dest : TCanvas ; x, y: integer; s: string; trans: byte); var MyBMP : TBitmap; BlendFunction : TBlendFunction; ASize : TSize; begin try MyBMP := TBitmap.create; GetTextExtentPoint32(MyBMP.Canvas.Handle,PCHAR(s),length(s),ASize); MyBMP.Width := MyBMP.Canvas.TextWidth(s); MyBMP.Height := MyBMP.Canvas.TextHeight(s); MyBMP.Canvas.TextOut(0,0,s); with BlendFunction do begin BlendOp := AC_SRC_OVER; BlendFlags := 0; SourceConstantAlpha := trans; AlphaFormat := 0; end; windows.AlphaBlend( Dest.Handle, // handle to destination DC x, // x-coord of upper-left corner y, // y-coord of upper-left corner MyBMP.Width, // width of destination rectangle MyBMP.Height, // height of destination rectangle MyBMP.Canvas.Handle, // handle to source DC 0, // x-coord of source upper-left corner 0, // y-coord of source upper-left corner MyBMP.Width, // width of source rectangle MyBMP.Height, // height of source rectangle blendFunction // alpha-blending function ); finally MyBMP.free; end; end; procedure TForm1.Button1Click(Sender: TObject); begin AlphaTextOut(image1.picture.bitmap.canvas ,0 ,0, 'A test string' ,200) end;--------------------------
-----------------------------------------------------------------------------------------------------
선택된 답
--------
hello yarek, here is my version that is specifically for a TPanel, instead of a bitmap. . . It is called - procedure BlendTextOut
the first parameter is for the Panel you want the text to go onto, the X and Y are position, and the Text parameter is the String to be drawn on the panel, the PerCentShow is a number from 1 to 99 for the percent of transparency to show the text, I left out the zero and 100 percent, since they make no sence for a blend text. . .
type TPerCent = 1..99; procedure BlendTextOut(aPanel: TPanel; X, Y: Integer; const Text: String; PerCentShow: TPerCent); type PColor32 = ^TColor32; TColor32 = packed record b, g, r, a: Byte; end; var BmpText, panelBmp: TBitmap; DCp: HDC; xx, yy, ColorBk, wid: Cardinal; pClPanel, pClBmp: PColor32; AmSh, AmBk: Single; begin if not Assigned(aPanel) then Exit; if (X > aPanel.Width-1) or (Y > aPanel.Height -1) then Exit; BmpText := TBitmap.Create; with BmpText, BmpText.Canvas do begin PixelFormat := pf32Bit; wid := ColorToRGB(aPanel.Color); Brush.Color := wid; Font.Assign(aPanel.Font); Width := TextWidth(Text); Height := TextHeight(Text); if (X < -Width) or (Y < -Height) then begin FreeAndNil(BmpText); Exit; end; Brush.Style := bsClear; TextOut(0, 0, Text); panelBmp := TBitmap.Create; panelBmp.PixelFormat := pf32Bit; panelBmp.Width := Width; panelBmp.Height := Height; end; DCp := GetDC(aPanel.Handle); BitBlt(panelBmp.Canvas.Handle,0,0, panelBmp.width, panelBmp.Height, DCp, X,Y, SRCCOPY); ReleaseDC(aPanel.Handle,DCp); ColorBk := wid; TColor32(ColorBk).r := TColor32(wid).b; TColor32(ColorBk).b := TColor32(wid).r; // ColorBk := ((wid and $FF) shl 16) or (wid and $FF00) or // ((wid and $FF0000) shr 16); AmSh := PerCentShow / 100; AmBk := 1.0 - AmSh; wid := Pred(BmpText.Width); pClPanel := panelBmp.ScanLine[panelBmp.Height - 1]; pClBmp := BmpText.ScanLine[BmpText.Height - 1]; for yy := BmpText.Height - 1 downto 0 do begin for xx := 0 to wid do begin if PDWORD(pClBmp)^ <> ColorBk then begin pClPanel.b := Round((pClBmp.b * AmSh) + (pClPanel.b * AmBk)); pClPanel.g := Round((pClBmp.g * AmSh) + (pClPanel.g * AmBk)); pClPanel.r := Round((pClBmp.r * AmSh) + (pClPanel.r * AmBk)); end; Inc(pClPanel); Inc(pClBmp); end; end; FreeAndNil(BmpText); DCp := GetDC(aPanel.Handle); BitBlt(DCp,x,y, panelBmp.width, panelBmp.Height, panelBmp.Canvas.Handle, 0,0, SRCCOPY); ReleaseDC(aPanel.Handle,DCp); FreeAndNil(panelBmp); end;
'프로그래밍???' 카테고리의 다른 글
몇 가지 메일 관련 에러 메시지를 참고하세요 (0) | 2008.11.12 |
---|---|
socket operation on non-socket (0) | 2008.11.05 |
난관 봉착... TCustomControl을 쓸것이냐, TGraphicControl을 쓸것이냐... (0) | 2008.08.02 |
알파 블랜드를 이용한 투명.... (0) | 2008.08.01 |
반투명 윈도우 만들기... (0) | 2008.08.01 |
난관 봉착... TCustomControl을 쓸것이냐, TGraphicControl을 쓸것이냐...
나도 저 문제에 봉착 했다.
델파이가 아니고 C++ Builder 지만...
어쨋든 두 툴이 거의 동일하다시피 하기 때문에...
지금의 문제는 TGraphicControl인 경우 배경을 투명하게 하는 것이 브러쉬만 바꿔주면 된다.
Canvas->Brush->Style = bsClear;
그러나 이 경우 Alpla를 적용할 방법이 없다.
투명도 조절이 불가능하다.
투명도를 조절하는 방법으로는 windows 2000이후에 나오는
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(Handle, 0, (255 * 70) / 100, LWA_ALPHA);
위의 두코드를 사용하면 되나 저 경우 윈도우 핸들이 있어야 한다.
따라서 윈도우 핸들이 있는 TCustomControl을 상속 받아 사용하는 방법이 있다.
이 경우 배경을 투명하게 하기 위한 처리를 해야 한다.
void __fastcall TDSMText::CreateParams(TCreateParams &Params)
{
TCustomControl::CreateParams(Params);
Params.ExStyle = Params.ExStyle | WS_EX_TRANSPARENT;
}
위와 같은 방법으로 윈도우 전체를 투명하게 한다.
void __fastcall TRectTracker::WMEraseBkgnd(Messages::TWMMouse &Message)
{
Message.Result = false;
}
위의 코드도 추가한다.
그러나, Tracker에서 배경이 희게 그려지는 현상이 발생하면서 다시 원점으로 갔다.
둘 중 하나를 선택한다면 TGraphicControl을 쓰고 싶다.
윈도우를 받아서 쓰는 부분은 정말 많은 문제가 발생하기 때문이다.
...
'프로그래밍???' 카테고리의 다른 글
socket operation on non-socket (0) | 2008.11.05 |
---|---|
How to add ALPHA to delphi TEXTOUT Tcanvas ? (0) | 2008.08.02 |
알파 블랜드를 이용한 투명.... (0) | 2008.08.01 |
반투명 윈도우 만들기... (0) | 2008.08.01 |
C++ Builder에서의 삽질(MouseDown) (0) | 2008.06.20 |
알파 블랜드를 이용한 투명....
알파 블랜드로 한번 해보자 ㅠ.ㅠ
------------------------------------------------------------------------------------------
GDI 에선 AlphaBlend 라는 함수로 가능하기는 하는데
찍을 부분의 이미지 색상과 혼합을 해야 제대로 구현이 됩니다
계산식이야 MSDN 에도 있고 여기 Q&A 에 검색해도 있습니다.
AlphaBlend 로 하다가 계산하는거 짜증나서
GDI+ 찾아 보니까 있더군여..
MSDN 에서 발췌했습니다.
여기 검색해봐도 없길래... 갖다 붙여 넣습니다... 참고하세요..
Using a Color Matrix to Set Alpha Values in Images
The Bitmap class (which inherits from the Image class) and the ImageAttributes class provide functionality for getting and setting pixel values. You can use the ImageAttributes class to modify the alpha values for an entire image, or you can call the SetPixel method of the Bitmap class to modify individual pixel values. For more information on setting individual pixel values, see Setting the Alpha Values of Individual Pixels.
The following example draws a wide black line and then displays an opaque image that covers part of that line.
Bitmap bitmap(L"Texture1.jpg");
Pen pen(Color(255, 0, 0, 0), 25);
// First draw a wide black line.
graphics.DrawLine(&pen, Point(10, 35), Point(200, 35));
// Now draw an image that covers part of the black line.
graphics.DrawImage(&bitmap,
Rect(30, 0, bitmap.GetWidth(), bitmap.GetHeight()));
The following illustration shows the resulting image, which is drawn at (30, 0). Note that the wide black line doesn't show through the image.
The ImageAtributes class has many properties that you can use to modify images during rendering. In the following example, an ImageAttributes object is used to set all the alpha values to 80 percent of what they were. This is done by initializing a color matrix and setting the alpha scaling value in the matrix to 0.8. The address of the color matrix is passed to the SetColorMatrix method of the ImageAttributes object, and the address of the ImageAttributes object is passed to the DrawImage method of a Graphics object.
// 다음 코드가 반투명 효과를 일으키게하는 소스이며.. 주석과 같이 4행4열의 0.8값을 주의깊게 보십시요
// 이 값을 바꿔주면서 이미지를 확인해 보시면 잘 알수 있을겁니다...
// 그럼.. 참고하세요..
// Create a Bitmap object and load it with the texture image.
Bitmap bitmap(L"Texture1.jpg");
Pen pen(Color(255, 0, 0, 0), 25);
// Initialize the color matrix.
// Notice the value 0.8 in row 4, column 4.
ColorMatrix colorMatrix = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.8f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
// Create an ImageAttributes object and set its color matrix.
ImageAttributes imageAtt;
imageAtt.SetColorMatrix(&colorMatrix, ColorMatrixFlagsDefault,
ColorAdjustTypeBitmap);
// First draw a wide black line.
graphics.DrawLine(&pen, Point(10, 35), Point(200, 35));
// Now draw the semitransparent bitmap image.
INT iWidth = bitmap.GetWidth();
INT iHeight = bitmap.GetHeight();
graphics.DrawImage(
&bitmap,
Rect(30, 0, iWidth, iHeight), // Destination rectangle
0, // Source rectangle X
0, // Source rectangle Y
iWidth, // Source rectangle width
iHeight, // Source rectangle height
UnitPixel,
&imageAtt);
During rendering, the alpha values in the bitmap are converted to 80 percent of what they were. This results in an image that is blended with the background. As the following illustration shows, the bitmap image looks transparent; you can see the solid black line through it.
Where the image is over the white portion of the background, the image has been blended with the color white. Where the image crosses the black line, the image is blended with the color black.
'프로그래밍???' 카테고리의 다른 글
How to add ALPHA to delphi TEXTOUT Tcanvas ? (0) | 2008.08.02 |
---|---|
난관 봉착... TCustomControl을 쓸것이냐, TGraphicControl을 쓸것이냐... (0) | 2008.08.02 |
반투명 윈도우 만들기... (0) | 2008.08.01 |
C++ Builder에서의 삽질(MouseDown) (0) | 2008.06.20 |
갑자기 느려진 디버깅... 원인을 찾다. (1) | 2008.04.25 |
반투명 윈도우 만들기...
원본은 트랙백을 쫓아가세요~~~
TGraphicControl을 반투명하게 만들어야 하는데...
원하는건 안나오고 계속 윈도 투명만들기 놀이만 나오네.. ㅠ.ㅠ
------------------------------------------------------------------------------------
[질문]
전에.. 윈도우를 만들때 RGB 를 섞어서.. 어떻게 만드는 걸 찾아서 해봤었거든요.
근데 그걸 날려먹어서리.. 다시 인터넷에 찾아볼려구 해두 안보이네요 ㅡ_ㅡ;;
좋은 하루 되시길~~~
[답변 - 금호창님이 답변하신글]
// 헤더파일에..여러 상수 지정. 옵션을 바꿀 수도 있슴.
#define WS_EX_LAYERED 0x00080000
#define LWA_COLORKEY 0x00000001
#define LWA_ALPHA 0x00000002
#define ULW_COLORKEY 0x00000001
#define ULW_ALPHA 0x00000002
#define ULW_OPAQUE 0x00000004
typedef BOOL(WINAPI *SLWA)(HWND, COLORREF, BYTE, DWORD); // 요거 선언해주고...
// 반투명하게 만드는 루틴.
SLWA pSetLayeredWindowAttributes = NULL; // 함수포인터 선언, 초기화.
HINSTANCE hmodUSER32 = LoadLibrary("USER32.DLL"); // 인스턴스 얻음.
pSetLayeredWindowAttributes=(SLWA)GetProcAddress(hmodUSER32,"SetLayeredWindowAttributes");
// 함수포인터 얻음.
HWND hwnd = this->m_hWnd; // 다이얼로그의 핸들 얻음.
SetWindowLong(hwnd, GWL_EXSTYLE,
GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
// pSetLayeredWindowAttributes(hwnd, 0, (255 * 70) / 100, LWA_ALPHA);
pSetLayeredWindowAttributes(hwnd, 0, (255 * 70) / 100, LWA_ALPHA);
// pSetLayeredWindowAttributes(hwnd, 0, (255 * 70) / 100, LWA_COLORKEY);
// 다이얼로그 반투명하게 만듬.
'프로그래밍???' 카테고리의 다른 글
난관 봉착... TCustomControl을 쓸것이냐, TGraphicControl을 쓸것이냐... (0) | 2008.08.02 |
---|---|
알파 블랜드를 이용한 투명.... (0) | 2008.08.01 |
C++ Builder에서의 삽질(MouseDown) (0) | 2008.06.20 |
갑자기 느려진 디버깅... 원인을 찾다. (1) | 2008.04.25 |
stack overflow와의 한판 싸움 (0) | 2008.04.23 |