2008년 2월 28일 목요일

Dephi 프로그램 Tip

초를 시분초로 분할
function ssTohhnnss(value: double): string;
var r, r1,r2: double;
begin
r:= Value;
r1:= Trunc(r / 60); //분
r2:= Trunc(r1 / 60); //시
r:= r - (r1 * 60);
r1:= r1 - (r2 * 60);
result:= FloatToStr(r2) + '시 ' + FloatToStr(r1) + '분 ' + FloatToStr(r) + '초';
end;

초값으로 정지하기 TTime없이

선언부
procedure Sleep(SleepSecs : Integer);

코딩부
procedure TForm1.Sleep(SleepSecs : Integer);
var
StartValue : LongInt;
begin
StartValue := GetTickCount;
while ((GetTickCount - StartValue) <= (SleepSecs * 1000)) do
Application.ProcessMessages;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Sleep(10);
end;

다른방법(선언 없음)

procedure TForm1.Button1Click(Sender: TObject);
begin
WaitForSingleObject(Handle,10);

end;

작업시 남은시간을 계산하는 함수

var gfdate: double;

procedure f_ListTimeStart;
var hh,mm,ss,ms: word;
begin
decodeTime(now,hh,mm,ss,ms);
gfdate:= (hh * 3600) + (mm * 60) + ss + ms / 1000;
end;

function f_ListTime(iMax,iPos: Integer): string;
var hh,mm,ss,ms: word;
f: double;
iValue: Int64;
begin
decodeTime(now,hh,mm,ss,ms);
f:= (hh * 3600) + (mm * 60) + ss + ms / 1000;
f:= f - gfdate;
f:= f / iPos * iMax - f;
iValue:= StrToInt64(FormatFloat('0',f));
sMsg := IntToStr(iValue div 3600) + '시 '
+ IntToStr(iValue mod 3600 div 60) + '분 '
+ IntToStr(iValue mod 60) + '초';
result:= sMsg;
end;

두년도의 차를 00년00월00일형식으로 계산하는 함수

//아래를보면좀복잡하지만
//예외적인숫자처리를위해서입니다.
//전에올린오라클함수는좀에러가있습니다.
//조만간에수정해서올리겠습니다.
//
//그리고이함수는퇴직정산에서입사일과퇴사일을주고
//00년00월00일근무했나하는것을계산하기위해서만들었습니다.

procedureYYMMDDCount(date1,date2:TDate;varyy,mm,dd:word);
var d1,d2,m1,m2:word;
begin
yy:=0;
mm:=0;
dd:=0;
d1:=0;

Date2:=IncDay(Date2);
yy:=YearsBetween(Date1,Date2);
Date1:=IncYear(Date1,yy);
m1:=DaysInMonth(Date1);
m2:=DaysInMonth(Date2-1);
d2:=DayOf(Date2-1);
Date2:=date2-d2;

if DayOf(Date1)>1 then
begin
d1:=m1-DayOf(Date1)+1;
Date1:=Date1+d1;
end;
if Date1 < Date2 then
begin
while Date1+DaysInMonth(Date1) < Date2 + 1 do
begin
Inc(mm);
Date1:=Date1+DaysInMonth(Date1)
end;
end;

if d1=m1 then
begin
Inc(mm);
d1:=0;
end;

if d2=m2 then
begin
Inc(mm);
d2:=0;
end;

d1:=d1+d2;
if d1>=m1 then
begin
d1:=d1-m1;
Inc(mm);
end;

if Date1>Date2 then
Inc(mm,-1);

dd:=d1;
yy:=yy+mm div 12;
mm:=mm mod 12;
end;

찾지말고 통 하자!

Bitmap그림을 흑백으로 그리기

procedure TForm1.Button1Click(Sender: TObject);
var x,y: integer;
c: TColor;
gray: Byte;
begin
for y:= 0 to Image1.Picture.Height do
begin
for x:= 0 to Image1.Picture.Width do
begin
c:= Image1.Picture.Bitmap.Canvas.Pixels[x,y];
gray:= (Byte(c) + Byte(c shr 8) + Byte(c shr 16)) div 3;
Image1.Picture.Bitmap.Canvas.Pixels[x,y]:= RGB(gray,gray,gray);
end;
Application.ProcessMessages;
end;
end;

Bitmap그림을 흑백으로 그리기 - Pointer사용(위 방법보다 빠름)

선언

procedure GrayBITMAP(Bitmap: TBitmap);
const
BPP = 4;
DefaultPixelFormat=pf32bit;

var P1: Pointer;
W1, H1, DataSize1, LineSize1: Integer;

x, y: Integer;
SrcP: PDWORD;
SrcR, SrcG, SrcB: Byte;
begin
with Bitmap do
begin
PixelFormat:=DefaultPixelFormat;
W1:=Width;
H1:=Height;
LineSize1:=DWORD(ScanLine[0])-DWORD(ScanLine[1]);
DataSize1:=LineSize1*H1;
P1:=ScanLine[H1-1];
end;

for x:=0 to W1 - 1 do
for y:=0 to H1 - 1 do
begin
SrcP:=Pointer(DWORD(P1)+ y * LineSize1 + x * BPP);

SrcR:= (SrcP^ and $0000FF);
SrcG:= (SrcP^ and $00FF00) shr 8;
SrcB:= (SrcP^ and $FF0000) shr 16;
SrcR:= (SrcR + SrcG + SrcB) div 3;

SrcP^:=(SrcR shl 16) or (SrcR shl 8) or SrcR;
end;
end;

사용

procedure TForm1.Button1Click(Sender: TObject);
begin
GrayBITMAP(Image1.Picture.Bitmap);
end;

Bitmap 파일을 MetaFile파일로 변환

function BitmapToMetaFile(Bitmap: TBitmap) : TMetaFile;
var mc: TMetaFileCanvas;
begin
result:= TMetaFile.Create;

result.Height := Bitmap.Height;
result.Width := Bitmap.Width;
result.Enhanced := True;

mc := TMetaFileCanvas.Create(result, 0); // BMP를 EMF의 canvas에 그리기(복사)
mc.Draw(0, 0, Bitmap);

mc.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
BitmapToMetaFile(Image1.Picture.Bitmap).SaveToFile('c:\test1.emf');
end;

bitmap을 jpeg로 변환

var
Jpeg1: TJpegImage;
Image1: TImage;
begin
Image1:= TImage.Create;
Jpeg1 := TJpegImage.Create;

// Bitmap을 file에서 불러오기
Image1.LoadFromFile('TestImage.BMP');

// Assign the BitMap to JPEG
Jpeg1.Assign(Image1.Picture.Bitmap);

// JPEG파일로 저장
Jpeg1.SaveToFile('TestJPEG.JPG');
end;

Bitmap을 Icon으로 바꾸려면...
먼저 두개의 Bitmap을 생성해야 하는데... Mask Bitmap(AND Bitmap이라 부른다.)과
Image Bitmap(XOR Bitmap이라 부른다.) 이렇게 두개의 Bitmap을 생성한 후...
Windows API 함수인 CreateIconIndirect()를 사용하여 바꿀 수 있다.

예)

procedure TForm1.Button1Click(Sender: TObject);
var
IconSizeX : integer;
IconSizeY : integer;
AndMask : TBitmap;
XOrMask : TBitmap;
IconInfo : TIconInfo;
Icon : TIcon;
begin
IconSizeX := GetSystemMetrics(SM_CXICON);
IconSizeY := GetSystemMetrics(SM_CYICON);

AndMask := TBitmap.Create;
AndMask.Monochrome := true;
AndMask.Width := IconSizeX;
AndMask.Height := IconSizeY;

AndMask.Canvas.Brush.Color := clWhite;
AndMask.Canvas.FillRect(Rect(0, 0, IconSizeX, IconSizeY));
AndMask.Canvas.Brush.Color := clBlack;
AndMask.Canvas.Ellipse(4, 4, IconSizeX - 4, IconSizeY - 4);

Form1.Canvas.Draw(IconSizeX * 2, IconSizeY, AndMask);

XOrMask := TBitmap.Create;
XOrMask.Width := IconSizeX;
XOrMask.Height := IconSizeY;

XOrMask.Canvas.Brush.Color := ClBlack;
XOrMask.Canvas.FillRect(Rect(0, 0, IconSizeX, IconSizeY));
XOrMask.Canvas.Pen.Color := clRed;
XOrMask.Canvas.Brush.Color := clRed;
XOrMask.Canvas.Ellipse(4, 4, IconSizeX - 4, IconSizeY - 4);

Form1.Canvas.Draw(IconSizeX * 4, IconSizeY, XOrMask);

Icon := TIcon.Create;
IconInfo.fIcon := true;
IconInfo.xHotspot := 0;
IconInfo.yHotspot := 0;
IconInfo.hbmMask := AndMask.Handle;
IconInfo.hbmColor := XOrMask.Handle;
Icon.Handle := CreateIconIndirect(IconInfo);

AndMask.Free;
XOrMask.Free;

Form1.Canvas.Draw(IconSizeX * 6, IconSizeY, Icon);

Application.Icon := Icon;

InvalidateRect(Application.Handle, nil, true);
Icon.Free;
end;

Canvas의 색상수
그래픽 프로그램을 작성할 때 Canvas의 색상수를 알고자 할 때가 있습니다
이때 사용하는 함수가 GetDeviceCaps() 입니다

TotalNumBitsPerPixel :=
GetDeviceCaps(Canvas.Handle, BITSPIXEL) *
GetDeviceCaps(Canvas.Handle, PLANES);

Return values of:

1 = 2 colors (monochrome)
4 = 16 colors
8 = 256 colors
15 = 32,768 colors
16 = 65,536 colors
24 = 16,777,216 colors

bitmap(그림)의 각종 정보 얻기

var
Info: PBitmapInfo;
InfoSize: Integer;
ImageSize: Longint;
Image: Pointer;
begin
// 아래 예제는 Image1.Picture.Bitmap의 높이와 폭을 구하는 예제입니다
// 더 많은 정보를 원하시면 원도우즈 API 도움말에서 BITMAPINFOHEADER 로
// 검색해 보시면 아래와 같은 구조체의 정보가 있습니다
// typedef struct tagBITMAPINFOHEADER{
// DWORD biSize;
// LONG biWidth;
// LONG biHeight;
// WORD biPlanes;
// WORD biBitCount
// DWORD biCompression;
// DWORD biSizeImage;
// LONG biXPelsPerMeter;
// LONG biYPelsPerMeter;
// DWORD biClrUsed;
// DWORD biClrImportant;
// } BITMAPINFOHEADER;

GetDIBSizes(Image1.Picture.Bitmap.Handle, InfoSize, ImageSize);
GetMem(Info, InfoSize);
try
GetMem(Image, ImageSize);
try
GetDIB(Image1.Picture.Bitmap.Handle, Image1.Picture.Bitmap.Palette, Info^, Image^);
ShowMessage(Info^.bmiHeader.biWidth);
ShowMessage(Info^.bmiHeader.biHeight);
finally
FreeMem(Image, ImageSize);
end;
finally
FreeMem(Info, InfoSize);
end;
end;

JPG 이미지파일에 주석 읽고/쓰기

{ This function reads the JPEG comment from the file }
function ReadComment(sFileName: string): string;
var
btL1, btL2, btS1, btS2,
btX : Byte;
fByte : file of Byte;
sComment, sTempComment: string;
lI : Longint;
begin
sTempComment := '';
sComment := '';
AssignFile(fByte, sFileName);
FileMode := 0;
Reset(fByte);
Read(fByte, btS1);
Read(fByte, btS1);
repeat
repeat
Read(fByte, btS1);
until btS1 = $FF;
Read(fByte, btS2);
Read(fByte, btL1);
Read(fByte, btL2);
sTempComment := '';
for lI := 1 to (256 * btL1 + btL2) - 2 do
if not Eof(fByte) then begin
Read(fByte, btX);
sTempComment := sTempComment + Chr(btX);
end;

if btS2 = $FE then
sComment := sTempComment;
until Eof(fByte) or (btS2 = $DA);
CloseFile(fByte);
Result := sComment;
end;

{ These functions write the JPEG comment to the file }
procedure WriteCommentTo(sFileName, sComment: string);
var
bNotYet : Boolean;
btA,
btS1, btS2, btX : Byte
fByteIn, fByteOut: file of Byte;
fFileIn, fFileOut: file;


p,pp : file;
i,ii,ss : longint;
s,r : string;
buf : array[1..1000000] of byte;
begin
r := '';
s := '';
bNotYet := True;
AssignFile(fByteIn, fname);
AssignFile(fByteOut, sFileName);
Reset(fByteIn);
Rewrite(fByteOut);
for btS1 := 1 to 2 do begin
Read(fByteIn, btA);
Write(fByteOut, btA);
end;
repeat
repeat
Read(fByteIn, btS1);
until btS1 = $FF;
Read(fByteIn, btS2);
Read(fByteIn, btL1);
Read(fByteIn, btL2);
s := '';
for i := 1 to (256 * btL1 + bTL2) - 2 do
if not Eof(fByteIn) then begin
Read(fByteIn, btX)l
s := s + Chr(btX);
end;
if ((btS2 and $F0) = $C0) and bNotYet and (sComment <> '') then begin
Write(fByteOut, $FFFE);
Write(fByteOut, (Length(sComment) + 2) div 256);
Write(fByteOut, (Length(sComment) + 2) mod 256);
for i := 1 to Length(sComment) do
Write(fByteOut, Ord(sComment[i]));
bNotYet := False;
end;
if s2 <> $FE then begin
Write(fByteOut, s1, s2, l1, l2);
for i := 1 to Length(s) do
Write(fByteOut, Ord(s[i]));
end;
until Eof(fByteIn) or (s2 = $DA);
i := FilePos(fByteIn);
ii := FilePos(fByteOut);
ss := FileSize(fByteIn);
CloseFile(fByteIn);
CloseFile(fByteOut);

AssignFile(fFileIn, fname);
AssignFile(fFileOut, nameoffile);
Reset(fFileIn, 1);
FileMode := 2;
Reset(fFileOut, 1);
Seek(fFileIn, i);
Seek(fFileOut, ii);
BlockRead(fFileIn, Buf, ss-i);
BlockWrite(fFileOut, Buf, ss-i);
CloseFile(fFileIn);
CloseFile(fFileOut);
end;

procedure WriteComment(sFileName, sComment: string);
var
sTempFile: string;
begin
(* To create a temporary file name it's best to use the
* CreateUniqueFileName() function from tip 4.7
*)
sTempFile := CreateUniqueFileName('C:\');
WriteCommentTo(sTempFile, sComment);
DeleteFile(sTempFile);
RenameFile(sTempFile, sFileName);
end;

찾지말고 통 하자!

ComboBox가 Drop-Down될때 Width 자동조정

procedure TForm1.AdjustDropDownWidth;
var i, ItemWidth: Integer;
begin
ItemWidth := 0;
// 최대 pixel수를 구한다
for i := 0 to ComboBox1.Items.Count - 1 do
if Canvas.TextWidth(ComboBox1.Items[i]) > ItemWidth then
ItemWidth := Canvas.TextWidth(ComboBox1.Items[i]) + 8;

// TComboBox 의 drop-down list 의 width를 변경하는 것은 단지
// pixel를 파라미터로 하여 CB_SETDROPPEDWIDTH 메시지를
// TComboBox 보내면 된다
SendMessage(ComboBox1.Handle,CB_SETDROPPEDWIDTH,ItemWidth, 0);
end;

Combobox에서 focus 가 올때 자동으로 펼쳐 내리기

procedure TForm1.ComboBox1Enter(Sender: TObject);
begin
SendMessage(ComboBox1.handle, CB_SHOWDROPDOWN, Integer(True), 0);
end;

procedure TForm1.ComboBox1Exit(Sender: TObject);
begin
SendMessage(ComboBox1.handle, CB_SHOWDROPDOWN, Integer(False), 0);
end;

Combobox에 color 넣기

procedure TForm1.FormCreate(Sender: TObject);
begin
with ComboBox1.Items do
begin
// 색상값을 문자로 바꾸어서 item으로 추가한다
// 추가된 값은 아래 OnDrawItem에서 color값으로만 쓰이고 화면에는
// 나타나지 않는다
Add(IntToStr(clRed));
Add(IntToStr(clFuchsia));
Add(IntToStr(clBlue));
Add(IntToStr(clGreen));
Add(IntToStr(clYellow));
end;
end;

procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
begin
with Control as TComboBox,Canvas do
begin
Brush.Color := clWhite;
FillRect(Rect);
InflateRect(Rect,-2,-2);
Brush.Color := StrToInt(Items[Index]); // item의 값을 color로 사용
FillRect(Rect);
end;
end;

Combobox 를 강제로 드롭시키기

// ComboBox에 Enter시 drop시킴
procedure TForm1.ComboBox1Enter(Sender: TObject);
begin
SendMessage(ComboBox1.handle, CB_SHOWDROPDOWN, Integer(True), 0);
end;

// ComboBox에서 Exit시 닫음
procedure TForm1.ComboBox1Exit(Sender: TObject);
begin
SendMessage(ComboBox1.handle, CB_SHOWDROPDOWN, Integer(False), 0);
end;

찾지말고 통 하자!

WebBrowser에 글추가

procedure WebString(Web: TWebBrowser; msg : string);
var tmp : string;
begin
tmp := Web.OleObject.Document.Body.innerHTML;
tmp := tmp + msg;
Web.OleObject.Document.Body.innerHTML := tmp;
Web.OleObject.Document.Body.Doscroll('PageDown');
end;

웹브라우져 컨트롤을 이용할때, enter key와 ctrl+c/x 동작 하도록 하기

작성자 : 임기택 [xor74]

IOleInPlaceActiveObject로 검색을 해보니 비슷한 문서들이 많이 있긴 하던데,
대부분 enter key에 대한 언급 뿐이더군요.
그래서 ctrl+c/ctrl+x에 대해서도 처리하도록 조금 수정 해 봤습니다.
참고하세요..

---------------------------------------------------------
uses
ActiveX, ClipBrd;

var
Form1: TForm1;
FOleInPlaceActiveObject: IOleInPlaceActiveObject;
SaveMessageHandler: TMessageEvent;

procedure TForm1.FormActivate(Sender: TObject);
begin
SaveMessageHandler := Application.OnMessage;
Application.OnMessage := MyMessageHandler;
end;

procedure TForm1.FormDeactivate(Sender: TObject);
begin
Application.OnMessage := SaveMessageHandler;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Application.OnMessage := SaveMessageHandler;
FOleInPlaceActiveObject := nil;
end;

procedure TForm1.MyMessageHandler(var Msg: TMsg; var Handled: Boolean);
const
DialogKeys: set of Byte = [VK_LEFT, VK_RIGHT, VK_BACK, VK_UP, VK_DOWN,
$30..$39, $41..$42, $44..$55, $57, $59..$5A];
begin
{ exit if we don't get back a webbrowser object }
if WebBrowser1 = nil then
begin
Handled := False;
Exit;
end;

if (Msg.hwnd = WebBrowser1.Handle) or (IsChild(WebBrowser1.Handle, Msg.hwnd)) then
begin
if ((Msg.message = WM_KEYDOWN) or (Msg.message = WM_KEYUP)) and (GetKeyState(VK_CONTROL) < 0) then
begin
Handled := (WebBrowser1.Application as IOleInPlaceActiveObject).TranslateAccelerator(Msg)=S_OK;
if (Msg.wParam = 67) then
Clipboard.AsText := WebBrowser1.OleObject.Document.selection.createRange().text;
if (Msg.wParam = 88) then
WebBrowser1.OleObject.Document.selection.createRange().text := '';
WebBrowser1.OleObject.Document.selection.createRange().select();
end
else
begin
Handled := not word(Msg.wParam) in [byte('A')..byte('Z'),VK_RETURN];
if Handled or (Msg.wParam = VK_RETURN) then
Handled := (WebBrowser1.Application as IOleInPlaceActiveObject).TranslateAccelerator(Msg)=S_OK;
end
end;

end;

WebBrowser에 메인과 프레임 읽기 완료 알기

procedure TForm1.WebBrowser1DocumentComplete(Sender: TObject;
const pDisp: IDispatch; var URL: OleVariant);
var
CurWebrowser: IWebBrowser;
TopWebBrowser: IWebBrowser;
Document: OleVariant;
WindowName: string;
begin
CurWebrowser := pDisp as IWebBrowser;
TopWebBrowser := (Sender as TWebBrowser).DefaultInterface;
if CurWebrowser = TopWebBrowser then
Memo1.Lines.Add('Complete document was loaded')
else;
begin
Document := CurWebrowser.Document;
WindowName := Document.ParentWindow.Name;
Memo1.Lines.Add(Format('Frame "%s" was loaded', [WindowName]));
end;
end;

TWebBrowser에서 특정문자를 부각시키고 위치하기

TWebBrowser에 불려진 윕분서에서 특정 문자열을 찾아서 부각시키고
찾은 문자열에 화면을 스크롤하여 보여줍니다.

아래의 코드는 찾은 문자열의 배경을 빨간색으로 바꾸어 줍니다.
prefix 를 바꾸어주면 다르게도 가능하겠죠. ^^

TEmbeddedWB에서도 WBLocateHighlight(WB: TWebBrowser; Text: string)을
WBLocateHighlight(WB: TEmbeddedWB; Text: string)으로 바꾸어주면 사용 할 수 있습니다.


uses mshtml;

procedure WBLocateHighlight(WB: TWebBrowser; Text: string) ;
const
prefix = '<span style="color:white; background-color: red;">';
suffix = '</span>';
var
tr: IHTMLTxtRange;
begin
if Assigned(WB.Document) then
begin
tr := ((wb.Document AS IHTMLDocument2).body AS IHTMLBodyElement).createTextRange;
while tr.findText(Text, 1, 0) do
begin
tr.pasteHTML(prefix + tr.htmlText + suffix) ;
tr.scrollIntoView(True) ;
end;
end;
end;

사용 방법은
WBLocateHighlight(WebBrowser1,'musk95') ;
입니다.

WebBrowser를 이용하여 폼 필드에 값 할당과 submit

i) 직접 접근 방법

WebBrowser1.OleObject.Document.frmMain.userID.value := 'k133';
// 폼 이름과 폼 필드 이름을 직접 코딩
WebBrowser1.OleObject.Document.frmMain.submit;
=> "구성원이 없습니다." 라는 에러 발생합니다.


ii) 이름으로 접근 방법

WebBrowser1.OleObject.Document.all.item('userID').value := 'k133';

WebBrowser1.OleObject.Document.all.item('submit').Click;

빈화면을 만들기


procedure NewDocument;
var
C: array[0..MAX_PATH-1] of Char;
FileName: String;
begin
GetTempPath( MAX_PATH, C );
FileName := C;
if FileName[ Length( FileName ) ] <> '\' then FileName := FileName + '\';
FileName := FileName + 'test.htm';
with TFileStream.Create( FileName, fmCreate ) do Free;
WebBrowser.Navigate( FileName );
end;

소스보기

procedure 프로시져명;
var MyDocument: OleVariant;
begin
MyDocument := WebBrowser1.Document;
Memo1.Lines.Clear;
// HTML 소스 보기
Memo1.Lines.Add(MyDocument.DocumentElement.InnerHTML);
// 일반 내용 보기
Memo1.Lines.Add(WebBrowser1.OleObject.Document.DocumentElement.InnerText);
Memo1.Visible:= True;
Memo1.Align:= alClient;
if Memo1.CanFocus then
Memo1.SetFocus;
end;

싸이트이동

WebBrowser1.Navigate('싸이트명');

WebBrowser1.Navigate('About:Blank'); //웹브라우져초기화

현재오픈된 URL가지고 오기

procedureOKGetURL(AStrings:TStrings);

functionWebBrowserCheck(constWebb:IWebBrowser2):Boolean;
var WebV:Variant;
Buf:string;
begin
WebV:=Webb;
Result:=False;
if Assigned(Webb)then
try
Buf:=WebV.Document.URL;
Result:=True;
except;
end;
end;

var
Count,i:integer;
mShellWindow:IShellWindows;
Webb:IWebBrowser2;
WebV:Variant;
begin
mShellWindow:=CreateComObject(CLASS_ShellWindows) as IShellWindows;
Count:=mShellWindow.Count;
fori:=0 to Count-1 do
begin
ifWebBrowserCheck(mShellWindow.Item(i)asIWebBrowser2) then
begin
try
Webb:=IWebBrowser2(mShellWindow.Item(i));
WebV:=Webb;
AStrings.Add(WebV.Document.URL);
except;
end;
end;
end;
end;

WebBrowser에서 이미지 찾아서 클릭하기

uses
MSHTML;

var
iDoc: IHtmlDocument2;
i: integer;
ov: OleVariant;
iDisp: IDispatch;
iColl: IHTMLElementCollection;
InputImage: HTMLInputImage;
begin
WebBrowser1.ControlInterface.Document.QueryInterface(IHtmlDocument2, iDoc);
if not Assigned(iDoc) then
begin
Exit;
end;
ov := 'INPUT';
iDisp := iDoc.all.tags(ov);
if Assigned(IDisp) then
begin
IDisp.QueryInterface(IHTMLElementCollection, iColl);
if Assigned(iColl) then
begin
for i := 1 to iColl.Get_length do
begin
iDisp := iColl.item(pred(i), 0);
iDisp.QueryInterface(HTMLInputImage, InputImage);
if Assigned(InputImage) then
begin
if InputImage.Name = 'submit' then
// if the name is submit / falls der name submit lautet
begin
InputImage.Click; // click it / klick es
end;
end;
end;
end;
end;
end;

// 2.

procedure TForm1.Button1Click(Sender: TObject);
var
i: Word;
Document: IHtmlDocument2;
str: string;
begin
// Schleife über alle Bilder im Webbrowser
for i := 0 to WebBrowser1.OleObject.Document.Images.Length - 1 do
begin
Document := WebBrowser1.Document as IHtmlDocument2;
// URL auslesen
Str := (Document.Images.Item(i, 0) as IHTMLImgElement).Href;
// Dateiname des Bildes überprüfen
if Pos('submit_icon.gif', str) <> 0 then
begin
((Document.Images.Item(i, 0) as IHTMLImgElement) as IHTMLElement).Click;
end;
end;
end;

찾지말고 통 하자!


TTreeView에서 node마다 Hint사용하기

메인메뉴나 기타 다른용도로 TTreeView를 사용하다 보면 Node마다 Hint를 보여줘야하는 경우가 있습니다.
이때 프로그램에 흐름은 Hint내용을 보관할 변수가 있어야 하고 그 변수를 초기화(TTreeView에 적용)하고 Hint내용을 변경하여 보여주는 단계로 이루어집니다.

//선언부
PRec = ^TRec;
TRec = record
Name: string; //TTreeNode를 동적으로 생성할 때 보여주는 이름
Hint: string; //TTreeNode마다 가지는 Hint
end;

//초기화부분 - FromCreate나 FormShow이벤트등에 코딩하면 됩니다.
var RecPtr: PRec;
TNNode1: TTreeNode;
begin
//여기서는 1개의 노드만 설정하지만 여러개를 설정해야하는 경우는 for문등 사용하면 됩니다.
New(RecPtr);
RecPtr^.Name:= 'Node1';
RecPtr^.Hint:= 'Node1Hint';
TNNode1:= AddObject(nil, RecPtr^.Name, RecPtr);
TNNode1.StateIndex:= 1;
end;

//사용부분 - 마우스가 움직일때 마다 Hint에 내용을 변경합니다.
procedure TForm1.TreeView1MouseMove(Sender: TObject;
Shift: TShiftState; X, Y: Integer);
var AHit: THitTests;
begin
with TreeView1 do begin
AHit := GetHitTestInfoAt(X, Y);
if not (htNowhere in AHit) then
Hint:= PRec(GetNodeAt(X, Y).Data)^.Hint;
end;
end;

TTreeView에서 Directory보여주기

procedure TForm1.GetDirectories(Tree: TTreeView; Directory: string;
Item: TTreeNode; IncludeFiles: boolean);
var SearchRec: TSearchRec;
ItemTemp: TTreeNode;
begin
Tree.Items.BeginUpdate;
if Directory[length(Directory)] <> '\' then Directory := Directory + '\';
if FindFirst(Directory + '*.*', faDirectory, SearchRec) = 0 then
begin
repeat
if (SearchRec.Attr and faDirectory = faDirectory) and (SearchRec.Name[1] <> '.') then
begin
if (SearchRec.Attr and faDirectory > 0) then
Item := Tree.Items.AddChild(Item, SearchRec.Name);
ItemTemp := Item.Parent;
GetDirectories(Tree, Directory + SearchRec.Name, Item, IncludeFiles);
Item := ItemTemp;
end else

if IncludeFiles then
if SearchRec.Name[1] <> '.' then
Tree.Items.AddChild(Item, SearchRec.Name);
until FindNext(SearchRec) <> 0;
FindClose(SearchRec);
end;
Tree.Items.EndUpdate;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
GetDirectories(TreeView1, 'C:\', nil, True);
end;

Treeview에서 오른쪽마우스버튼으로 선택하기

var AHit: THitTests;
begin
with TreeViewMain do
begin
AHit := GetHitTestInfoAt(X, Y);
if not (htNowhere in AHit) then
Selected := GetNodeAt(X, Y);
end;

end;

TreeView에서 각 node item별로 색깔 부여하기

// 내용 : TreeView에서 각 node item별로 색깔 부여하기
// 취지 : TreeView에 경보난 시스템을 등록시킨 후 경보가 발생하면
// 해당 node의 폰트(혹은 brush) Color를 변경시켜 주고 싶어서
// 만들어 보았습니다.
// 추가 : 잘 분석해보시면 TList를 이해하는데도 도움이 될겁니다.
// 작성일자 : 2000.02.15
// 작성자 : 김준성

unit Unit10;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, StdCtrls, ExtCtrls;

type
TRectreeList = Record
NName : String[20] ;
SName : String[10] ;
end;

TForm1 = class(TForm)
TV: TTreeView;
Button2: TButton;
Edit1: TEdit;
Edit2: TEdit;
Button4: TButton;
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure TVCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
State: TCustomDrawState; var DefaultDraw: Boolean);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure ChangeTreeColor(Flag:Byte; NName,SName: String);
end;

var
Form1: TForm1;
treeList : TList ;

implementation

{$R *.DFM}

// Item 색상을 변경
procedure TForm1.Button4Click(Sender: TObject);
begin
ChangeTreeColor(1, Edit1.Text, Edit2.Text);
end;

// item 색상을 원래대로...
procedure TForm1.Button2Click(Sender: TObject);
begin
ChangeTreeColor(2, Edit1.Text, Edit2.Text);
end;

// 등록된 값들이 저장되어 있는 값
// TList는 링크드리스트 형태로써 유용하게 사용할 수 있다.
procedure TForm1.ChangeTreeColor(Flag:Byte; NName,SName: String);
var
i : Integer ;
PTreeList : ^TRectreeList ; // TOfcs을 가리키는 포인터의 선언.
begin
case Flag of
1 : begin
// TreeList.Clear;
New(PTreeList);
PTreeList^.NName := Edit1.Text ;
PTreeList^.SName := Edit2.Text ;
TreeList.Add(PTreeList) ;
TV.Repaint ;
end;
2 : begin
for i := TreeList.Count-1 downto 0 do
if (Edit1.Text = TRectreeList(TreeList.Items[i]^).NName) and
(Edit2.Text = TRectreeList(TreeList.Items[i]^).SName) then
TreeList.Delete(i) ;
end;
end;
TV.Repaint ;
end;


// Item의 값을 비교하여 item의 Color를 변경
procedure TForm1.TVCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
State: TCustomDrawState; var DefaultDraw: Boolean);
var
i : Integer ;
begin
with TV.Canvas do begin
Font.Color := clBlack ; // 선택된 item의 폰트 컬러
if cdsSelected in State then
Brush.Color := clAqua ; // 선택된 item의 Brush Color

case Node.Level of
0 : begin
for i := 0 to treeList.Count-1 do
if (node.Text = TRectreeList(treeList.Items[i]^).NName) then begin
// Brush.Color := clFuchsia; // item의 Brush Color
Font.Color := clFuchsia; // item의 폰트 Color
break;
end;
end;
1 : begin
for i := 0 to treeList.Count-1 do
if (node.Parent.Text = TRectreeList(treeList.Items[i]^).NName) and
(node.Text = TRectreeList(treeList.Items[i]^).SName) then begin
Font.Color := clRed ; // item의 폰트 Color
break;
end;
end;
end; //case
end;
end;


// TreeView에 디폴트 값 등록
procedure TForm1.FormShow(Sender: TObject);
var topNode, subNode : TTreenode ;
begin
TV.Items.Clear ;
topNode := TV.TopItem ;
subNode := TV.Items.AddChild(topNode, 'aaa');
TV.items.AddChild(subNode,'박찬호');
TV.items.AddChild(subNode,'선동열');
TV.items.AddChild(subNode,'이동국');
TV.items.AddChild(subNode,'황선홍');
subNode := TV.Items.AddChild(topNode, 'bbb');
subNode := TV.Items.AddChild(topNode, 'ccc');
TV.items.AddChild(subNode,'김대중');
TV.items.AddChild(subNode,'김영삼');
TV.items.AddChild(subNode,'노태우');
TV.items.AddChild(subNode,'전두환');
subNode := TV.Items.AddChild(topNode, 'ddd');
subNode := TV.Items.AddChild(topNode, 'eee');
subNode := TV.Items.AddChild(topNode, 'fff');

Edit1.Text := 'ccc' ;
Edit2.Text := '전두환' ;
TV.FullExpand ;
ChangeTreeColor(1, Edit1.Text, Edit2.Text);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
treeList := TList.Create; // Cleate
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
treeList.Clear;
treeList.Free;
end;

end.

찾지말고 통 하자!


소켓 파일 다운로드

작성자 : 김도완 [델파이초보]

출처 : http://blog.naver.com/pupplecoffee.do

= 소켓을 이용한 파일 다운로드 =

procedure DownloadFile(strHost, strRemoteFileName, strLocalFileName: string;
ClientSocket: TClientSocket);
var
intReturnCode: Integer;
s: string;
szBuffer: array[0..128] of Char;
FileOut: TFileStream;
begin
if strRemoteFileName[1] <> '/' then
strRemoteFileName := '/' + strRemoteFileName;

FileOut := TFileStream.Create(strLocalFileName, fmCreate);
try
with ClientSocket do
begin
Host := strHost;
ClientType := ctBlocking;
Port := 80;

try
Open;
{send query}
s := 'GET ' + strRemoteFileName + ' HTTP/1.0'#13#10 +
'Host: ' + strHost + #13#10#13#10;
intReturnCode := Socket.SendBuf(Pointer(s)^, Length(s));

if intReturnCode > 0 then
begin
{receive the answer}
{ iterate until no more data }
while (intReturnCode > 0) do
begin
{ clear buffer before each iteration }
FillChar(szBuffer, SizeOf(szBuffer), 0);

{ try to receive some data }
intReturnCode := Socket.ReceiveBuf(szBuffer, SizeOf(szBuffer));

{ if received a some data, then add this data to the result string }
if intReturnCode > 0 then
FileOut.Write(szBuffer, intReturnCode);
end
end
else
MessageDlg('No answer from server', mtError, [mbOk], 0);

Close;
except
MessageDlg('No connection', mtError, [mbOk], 0);
end;
end;
finally
FileOut.Free
end;
end;

사용방법
procedure TForm1.Button1Click(Sender: TObject);
begin
DownloadFile('www.scalabium.com', '/forums.htm', 'd:\forums.htm', ClientSocket1);
end;

sock(indy)를 이용한 화일전송

인터넷이 보편화되면서 채팅프로그램등 여러프로그램에서 화일전송을 지원합니다.
아래 예제는 이런한 화일전송을 TIdTCPServer, TIdTCPClient콤포넌트를 사용해서 만든 예제합니다.

Server쪽은 TIdTCPServer컴포넌트한개만 사용합니다.
Client쪽은 TIdTCPClient, TEdit컴포넌트 한개씩, TButton두개를 사용합니다.
이름은 default값을 그냥 사용하고 이벤트 처리만 하면 프로그램 끝.

Server Event List

Form1.OnCreate:= FormCreate;
Form1.OnDestroy:= FormDestroy;
IdTCPServer1.OnExecute:= IdTCPServer1Execute;
IdTCPServer1.OnConnect:= IdTCPServer1Connect;
IdTCPServer1.OnDisConnect:= IdTCPServer1Disconnect;

Client Event List

Button1.OnClick:= Button1Click; <font color = blue>//접속시 사용</font>
Button2.OnClick:= Button2Click; <font color = blue>//화일전송시 사용</font>
IdTCPClient1.OnConnected:= IdTCPServer1Connect;
IdTCPClient1.OnDisconnected:= IdTCPServer1Disconnect;

Server 전체소스


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, IdBaseComponent, IdComponent, IdTCPServer,
ComCtrls;

type
TForm1 = class(TForm)
IdTCPServer1: TIdTCPServer;
procedure IdTCPServer1Execute(AThread: TIdPeerThread);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure IdTCPServer1Connect(AThread: TIdPeerThread);
procedure IdTCPServer1Disconnect(AThread: TIdPeerThread);
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var s: String;
Stream: TFileStream;
begin
s:= AThread.Connection.ReadLn;
if s='FileDown' then begin
try
Stream:= TFileStream.Create('c:\test1.jpg',fmOpenRead);
AThread.Connection.OpenWriteBuffer;
AThread.Connection.WriteStream(Stream);
AThread.Connection.CloseWriteBuffer;
Stream.Free;
AThread.Connection.Disconnect;
except
end;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
if not IdTCPServer1.Active then IdTCPServer1.Active:= true;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
IdTCPServer1.Active:= False;
end;

procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
Caption:= '클라이언트와 연결됨!';
end;

procedure TForm1.IdTCPServer1Disconnect(AThread: TIdPeerThread);
begin
Caption:= '클라이언트와 연결이 해제됨!';
end;

end.

Client 전체소스


unit Unit2;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, ExtCtrls,
StdCtrls, ComCtrls;

type
TForm2 = class(TForm)
IdTCPClient1: TIdTCPClient;
Button1: TButton;
Button3: TButton;
Edit1: TEdit;
Image1: TImage;
procedure Button1Click(Sender: TObject);
procedure IdTCPClient1Connected(Sender: TObject);
procedure IdTCPClient1Disconnected(Sender: TObject);
procedure Button3Click(Sender: TObject);
end;

var
Form2: TForm2;

implementation

{$R *.DFM}

procedure TForm2.Button1Click(Sender: TObject);
begin
IdTCPClient1.Host:= Edit1.Text;
IdTCPClient1.Connect;
end;

procedure TForm2.IdTCPClient1Connected(Sender: TObject);
begin
Caption:= '서버와 연결됨!';
end;

procedure TForm2.IdTCPClient1Disconnected(Sender: TObject);
begin
Caption:= '서버와 연결이 해제됨!';
end;

procedure TForm2.Button3Click(Sender: TObject);
var Stream: TFileStream;
begin
Stream:= TFileStream.Create('c:\Test2.jpg',fmCreate);
with IdTCPClient1 do
try
WriteLn('FileDown');
ReadStream(Stream,-1,true);
finally
FreeAndNil(Stream);
end;
end;

end.

TServerSocket Control의 실행 순서

By YSU

먼저 TServerSocket의 threadblocking mode를 이해하기 위해 실행순서를 분석하
므로 non-blocking부분은 제외함을 말힌다.
TServerSocket의 실행 순서를 알기 전에 간단히 server의 동작 방식을 이해해야
한다. server는 무엇인가를 service하기 위해 있는거다. service를 효율적으로 하는
방식은 꼭 computer안에만 있는건 아니다.
114안내를 보자. 전화를 걸면 맨 먼저 듣는 소리는 "안내 1234호 입니다" 다.
즉 많은 안내원중에 1234번 안내원에게 연결해 준다는 소릴게다. 그리고 안내원의
"네네 안녕하십니까?"가 나오고, 내가 번호를 물으면 안내를 해주고 전화를 끋는다.
이게 server하고 똑같다. 그럼 server는 어떻게 동작하나, 먼저 client의 연결이
오면 연결을 받고(accept) 그리고 대기하고 있는 service에게 연결을 전달해 준다.
그리고 또 기다리다 연결을 받고(accept)또 service에게 전해주고 이걸 반복한다.
114의 "안내 1234호 입니다" 처럼. 그리고 나면 service가 그 연결을(socket) 받아
요청을 듣고, 응답을 하고, 이를 일정회 반복하고 연결을 종료한다. 그리고 114는
연중 무휴이겠지만 처음 server를 시작하는걸 Listen이라고 한다.
자그럼 TServerSocket을 보자 위의 예는 threadbloking mode의 예이다. 이 경우
TServerSocket의 TServerAcceptThread가 첫 accept를 하는 부분이고,
TServerClientThread는 service를 하는 부분이다. server를 만드는 것은 이
service를 구현 하는 것이다. 그리고 TServerWinSocket이 첫 연결하는 전화기라면
TServerClietnWinSocket이 안내양이 사용하는 전화기다.
그럼 TServerSocket의 실행 순서를 확인해 보자.

1. TServerSocket의 생성
Form이 생성 될때 자동으로 호출되며, FServerSocket := TServerWinSocket.Create;
로 TServerWinSocket을 생성한다.

2. TServerSocket.Active := true로 설정
TServerSocket.SetActive(true)를 호출하고, 이함수는 내부에서 FActive := true;
를 지정하고 DoActivate(true)를 호출한다.

DoActivate(true)는 TServerWinSocket.Listen(FHost,FAddress,FService,FPort,5)를
호출한다.

TServerWinSocket.Listen은 TCustomWinSocket.Listen(FHost,FAddress,FService,
FPort,5)를 호출하고, FServerAcceptThread := TServerAcceptThread.Create를
생성한다.

TCustomWinSocket.Listen은 FSocket := socket(PF_INET,SOCK_STREAM,IPPROTO_IP)로
실재 WinSock32를 호출하고, InitSocket(FHost,FAddress,FService,FPort,False)에
서 TSockAddrIn를 구한다. DoSetASyncStyle에서 WSAAsyncSelect(FSocket,0,0,
Longint(Byte(FAsyncStyles)))와 ioctlsocket(FSocket,FIONBIO,0)를 WinSock32
함수를 호출하고 Event(Self,seListen)를 호출한다.

TCustomWinSocket.Event(Self,seListen)은 FOnListen(Self,Socket)에 등록된 event
handler를 출한다.


3. TServerAcceptThread의 Execute 실행
TServerWinSocket.Accept(FServerSocket.SocketHandle)를 계속 실행한다.

TServerWinSocket.Accept는 getsockopt(INVALID_SOCKET,SOL_SOCKET,SO_OPENTYPE,
PChar(@OldOpenType),Len)로 시작하고, setsockopt(INVALID_SOCKET,SOL_SOCKET,
SO_OPENTYPE,PChar(@OldOpenType),Len)로 끝낸다 즉 OpenType을 보관해 놓았다가
다시 되 돌린다. 그 사이에서는 setsockopt(INVALID_SOCKET,SOL_SOCKET,
SO_OPENTYPE,PChar(@SO_SYNCHRONOUS_NONALERT),Len)로 setting을 변경하고,
ClientWinSocket := WinSock.accept(Socket, @Addr, @Len)인 WinSock32함수를
호출해 실재 connection을 기다리게 된다. 그리고 ClientSocket :=
GetClientSocket(ClientWinSocket)을 호출해 TServerClientWinSocket을 얻고
FOnSocketEvent(Self, ClientSocket, seAccept)로 지정된 event handler를 호출
하고 ClientSocket.ASyncStyles := []를 지정하고 GetServerThread(ClientSocket)
로 TServerClinetThread를 얻는다.

GetClientSocket은 FOnGetSocket(Self,Socket,Result)로 지정된 event handler로
TServerClinetWinSocket을 얻을려고 시도해보고,
안되면 TServerClientWinSocket.Create(Socket, Self)로 직접 생성한다.

GetServerThread는 먼저 FActiveThreads에서 ClientSocket = nil인 즉 현재
service를 않하는 TServerClientThread를 얻어보고, 만일 있으면
TServerClientThread.ReActivate(ClientSocket)를 호출한다. 만일 현재 노는게
없으면 FOnGetThread(Self,ClientSocket,Result)로 지정된 event handler를 호출
해서 얻도록하고 안되면, DoCreateThread(ClientSocket)로 직접 생성한다.

DoCreateThread은 TServerClientThread.Create를 호출해 생성하고,
TServerClientThread.Create내에서 ReActivate(ASocket)을 호출한다. 즉 어떻게
한던 TServerClientThread.ReActivate(ClientSocket)은 항상 호출 된다.

ReActivate은 TServerClientWinSocket과 TServerWinSocket를 저장하고
TServerWinSocket.AddThread(Self)로 자신을 등록하고,
TServerClientWinSocket.OnSocketEvent := HandleEvent과
TServerClientWinSocket.OnErrorEvent := HandleError의 event handler를 연결
한다. 마지막으로 Windows.SetEvent(Handle)를 호출한다.

4. TServerClientThread의 Execute 실행
TServerWinSocket.ThreadStart(Self)로 FOnThreadStart(Self,AThread)인 등록된
event handle을 맨 먼제 호출하고, TServerWinSocket.ThreadEnd(Self)로
FOnThreadEnd(Self, AThread)인 등록된 event handler를 마지막으로 호출한다.
그리고 IF StartConnect THEN ClientExecute;
IF EndConnect THEN Break;
를 무한 반복한다.

StartConnect는 WaitForSingleObject(Handle,INFINITE)로 기다리다. terminated를
확인하여 terminate가 않됬으면 true를 돌려준다.
EndConnect는 terminate이고 KeepInCache가 아니면 true를 돌려준다.

ClientExecute는 IF select(0, @FDSet, nil, nil, @TimeVal) > 0로 읽을게 있으면
TServerClientWinSocket.ReceiveBuf(FDSet, -1)를 읽어봐 읽어지면
Synchronize(DoRead)로 TServerWinSocket.ClinetEvent(seRead)를 호출하고
ClinetRead를 거처 FOnClinetRead에 등록된 event handler를 호출한다.
그리고 IF select(0, nil, @FDSet, nil, @TimeVal) > 0로 읽을게 있으면
TServerClientWinSocket.ReceiveBuf(FDSet, -1)를 읽어봐 쓸게있으면
Synchronize(DoWrite)로 TServerWinSocket.ClinetEvent(seWrite)를 호출하고
ClinetWrite를 거처 FOnClinetWrite에 등록된 event handler를 호출한다.

5. Window가 message를 보내오는 경우
TServerClientWinSocket.OnSocketEvent
TServerClientThread.HandleEvent(Sender, Socket, SocketEvent)
Event(SocketEvent)
TServerWinSocket.ClientEvent(Self, ClientSocket, SocketEvent)
ClientConnect(Socket)
OR ClientDisconnect(Socket)
OR ClientRead(Socket)
OR ClientWrite(Socket)
FOnClientConnect(Socket)
OR FOnClientDisconnect(Socket)
OR FOnClientRead(Socket)
OR FOnClientWrite(Socket)에 등록된 event handler를 호출한다.

TServerClientWinSocket.OnErrorEvent
TServerClientThread.HandleError(Sender,Socket,ErrorEvent,ErrorCode)
Error(ErrorEvent, ErrorCode)
TServerWinSocket.ClientError(Sender,Socket,ErrorEvent,ErrorCode)
ClinetErrorEvent(Socket, ErrorEvent, ErrorCode)
FOnClinetError(Socket, ErrorEvent, ErrorCode)
에 등록된 event handler를 호출한다.

6. 참고
indent는 호출되어지는 순서를 나타낸다.

TServerSocket.Create
FServerSocket := TServerWinSocket.Create;

TServerSocket.Active := true;
TServerSocket.SetActive(true);
FActive := true;
DoActivate(true);
TServerWinSocket.Listen(FHost, FAddress, FService, FPort, 5);
TCustomWinSocket.Listen(FHost, FAddress, FService, FPort, 5);
FSocket := socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
SockAddrIn := InitSocket(FHost, FAddress, FService, FPort, False);
TSockAddrIn.sin_family := PF_INET;
TSockAddrIn.sin_addr := {LookupName(FHost)
OR inet_addr(PChar(FAddress))
OR INADDR_ANY
};
TSockAddrIn.sin_port := {htons(LookupService(FService))
OR htons(FPort)
};
DoSetASyncStyles;
IF AsyncStyles
WSAAsyncSelect(FSocket, CM_SOCKETMESSAGE, Handle,
Longint(Byte(FAsyncStyles)));
ELSE
WSAAsyncSelect(FSocket, 0, 0, Longint(Byte(FAsyncStyles)));
ioctlsocket(FSocket, FIONBIO, 0);
Event(Self, seListen);
FOnListen(Self, Socket);
FServerAcceptThread := TServerAcceptThread.Create(False, Self);
TThread.Create(False);

....
TServerAcceptThread.Execute;
TServerWinSocket.Accept(FServerSocket.SocketHandle);
getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
PChar(@OldOpenType),Len);
IF stThreadBlocking
setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
PChar(@SO_SYNCHRONOUS_NONALERT), Len);
ClientWinSocket := WinSock.accept(Socket, @Addr, @Len);
ClientSocket := GetClientSocket(ClientWinSocket);
{FOnGetSocket(Self, Socket, Result)
OR TServerClientWinSocket.Create(Socket, Self)
};
FOnSocketEvent(Self, ClientSocket, seAccept);
IF stThreadBlocking
ClientSocket.ASyncStyles := [];
GetServerThread(ClientSocket);
{SELECT TServerClientThread
FROM FActiveThreads
WHERE ClientSocket = nil
TServerClientThread.ReActivate(ClientSocket);
TServerClientWinSocket := ASocket;
TServerWinSocket := FClientSocket.ServerWinSocket;
TServerWinSocket.AddThread(Self);
FActiveThreads.Add(Self);
TServerClientWinSocket.OnSocketEvent := HandleEvent;
TServerClientWinSocket.OnErrorEvent := HandleError;
FEvent.SetEvent;
Windows.SetEvent(Handle);
OR FOnGetThread(Self, ClientSocket, Result)
OR DoCreateThread(ClientSocket)
TServerClientThread.Create(False, ClientSocket);
ReActivate(ASocket); <- 상동
};
setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
PChar(@OldOpenType), Len);

...
TServerClientThread.Execute;
TServerWinSocket.ThreadStart(Self);
FOnThreadStart(Self, AThread);
WHILE
IF StartConnect
WaitForSingleObject(Handle, INFINITE)
RETURN NOT terminated
ClientExecute;
FD_ZERO(FDSet);
FD_SET(TServerClientWinSocket.SocketHandle, FDSet);
TimeVal.tv_sec := 0;
TimeVal.tv_usec := 500;
IF select(0, @FDSet, nil, nil, @TimeVal) > 0
IF TServerClientWinSocket.ReceiveBuf(FDSet, -1) = 0
Break
ELSE
Synchronize(DoRead);
TServerWinSocket.ClinetEvent(seRead);
ClinetRead
FOnClinetRead
IF select(0, nil, @FDSet, nil, @TimeVal) > 0
Synchronize(DoWrite);
TServerWinSocket.ClinetEvent(seWrite);
ClinetWrite
FOnClinetWrite
IF EndConnect
RETURN terminated AND NOT KeepInCache
Break;
TServerWinSocket.ThreadEnd(Self);
FOnThreadEnd(Self, AThread);

...
TServerClientWinSocket.OnSocketEvent;
TServerClientThread.HandleEvent(Sender, Socket, SocketEvent);
Event(SocketEvent);
TServerWinSocket.ClientEvent(Self, ClientSocket, SocketEvent);
{ClientConnect(Socket)
OR ClientDisconnect(Socket)
OR ClientRead(Socket)
OR ClientWrite(Socket)
};
{FOnClientConnect(Socket)
OR FOnClientDisconnect(Socket)
OR FOnClientRead(Socket)
OR FOnClientWrite(Socket)
};

...
TServerClientWinSocket.OnErrorEvent;
TServerClientThread.HandleError(Sender,Socket,ErrorEvent,ErrorCode);
Error(ErrorEvent, ErrorCode);
TServerWinSocket.ClientError(Sender,Socket,ErrorEvent,ErrorCode);

ClinetErrorEvent(Socket, ErrorEvent, ErrorCode);
FOnClinetError(Socket, ErrorEvent, ErrorCode);

찾지말고 통 하자!


전체경로 폴더생성

function ForceDirectories(Dir: string): Boolean;

or

procedure pCreateDir(sPath: string);
var s: string;
sList: TStrings;
i: Integer;
begin
s:= sPath;
if DirectoryExists(s) then
Exit;

sList:= TStringList.Create;
try
while pos('\',s) > 0 do
begin
sList.Add(Copy(s,1,Pos('\',s)));
Delete(s,1,Pos('\',s));
end;
if Length(s) > 0 then
sList.Add(s);
s:= '';
for i:= 0 to sList.Count - 1 do
begin
s:= s + sList[i];
if not DirectoryExists(s) then
begin
CreateDir(s);
end;
end;
finally
sList.Free;
end;
end;

바로가기 단축아이콘에서 실행파일경로명 구하기

uses
ShlObj, ActiveX, ComObj;

function ShortCutToExeFileName(ShortCutPath:String):string;
var
MyObject : IUnknown;
MySLink : IShellLink;
MyPFile : IPersistFile;
WFileName : WideString;
WFindData : TWin32FindDataA;
begin
MyObject := CreateComObject(CLSID_ShellLink);
MySLink := MyObject as IShellLink;
MyPFile := MyObject as IPersistFile;

Result := '';
WFileName := ShortCutPath + #0;
if MyPFile.Load(PWChar(WFileName), STGM_READ) = S_OK then
with MySLink do
begin
SetLength(WFileName, 255);
GetPath(PChar(WFileName), Length(WFileName), WFindData, SLGP_UNCPRIORITY);
Result := StrPas(PChar(WFileName));
end;
end;

TextFile 읽기

var F: TextFile;
s: string;
begin
if OpenDialog1.Execute then
begin
AssignFile(F, OpenDialog1.FileName);
Reset(F);
Memo1.Lines.Clear;
while not Eof(F) do
begin
Readln(F, s);
Memo1.Lines.Add(s1);
end;
CloseFile(F);
end;
end;

ShellExecute 예제

procedure ExecFile (const Filename: String);
begin
ShellExecute(0, nil, PChar(Filename), nil,
PChar(GetCurrentDir), SW_SHOWDEFAULT);
end;

사용 예) ExecFile ('C:\Windows\바탕 화면\ACDSee 32.lnk');

Path 환경설정 읽기

function GetEnvVar(const csVarName : string ) : string;
var pc1, pc2 : PChar;
begin
pc1 := StrAlloc( Length( csVarName )+1 );
pc2 := StrAlloc( cnMaxVarValueSize + 1 );

StrPCopy( pc1, csVarName );

GetEnvironmentVariableA(
pc1, pc2, cnMaxVarValueSize );

Result := StrPas( pc2 );

StrDispose( pc1 );
StrDispose( pc2 );
end;

Internet으로부터 파일을 다운로드 하기

uses
URLMon;

if URLDownloadToFile(nil, 'http://www.crosswinds.net/~realmind/English/FAQ/mDF.html', 'c:\HTML\Merlins Forge\mDF.html', 0, nil) <> 0 then
MessageBox(Handle, 'An error ocurred while downloading the file.', PChar(Application.Title), MB_ICONERROR or MB_OK);

INI화일 사용

uses Inifiles;

with TIniFile.Create('SinyFile.ini') do
try
WriteInteger('Position','Top' ,Top);
WriteInteger('Position','Width' ,Width);
WriteInteger('Position','Left' ,Left);
WriteInteger('Position','Height',Height);
finally
Free;
end;

with TIniFile.Create('SinyFile.ini') do
try
Top := ReadInteger('Position','Top',0);
Width := ReadInteger('Position','Width',800);
Left := ReadInteger('Position','Left',0);
Height := ReadInteger('Position','Height',570);
finally
Free;
end;

파일의 날짜시간알기


function GetFileDate(TheFileName: string): string;
var FHandle: integer;
begin
FHandle := FileOpen(TheFileName, 0);
try
Result := DateTimeToStr(FileDateToDateTime(FileGetDate(FHandle)));
finally
FileClose(FHandle);
end;
end;

function GetFileLastAccessTime(sFileName: string): TDateTime;
var
ffd : TWin32FindData;
dft : DWord;
lft : TFileTime;
h : THandle;
begin
// get file information
h := Windows.FindFirstFile(PChar(sFileName), ffd);
if(INVALID_HANDLE_VALUE <> h)then
begin
//
// we're looking for just one file,
// so close our "find"
Windows.FindClose( h );
//
// convert the FILETIME to
// local FILETIME
FileTimeToLocalFileTime(
ffd.ftLastAccessTime, lft );
//
// convert FILETIME to
// DOS time
FileTimeToDosDateTime(lft,
LongRec(dft).Hi, LongRec(dft).Lo);
//
// finally, convert DOS time to
// TDateTime for use in Delphi's
// native date/time functions
Result := FileDateToDateTime(dft);
end;
end;

화일을 마우스로 이동하기

선언부
procedure WMDROPFILES(var Message: TWMDROPFILES);
message WM_DROPFILES;
코딩부
procedure TForm1.FormCreate(Sender: TObject);
begin
{Let Windows know we accept dropped files}
DragAcceptFiles(Self.Handle, True);
end;

procedure TForm1.WMDROPFILES(var Message: TWMDROPFILES);
var
NumFiles: LongInt;
i: LongInt;
Buffer: array[0..255] of Char;
begin
{How many files are being dropped}
// NumFiles := DragQueryFile(Message.Drop, -1, nil, 0);
NumFiles := DragQueryFile(Message.Drop, 0, nil, 0);
{Accept the dropped files}
for i := 0 to (NumFiles - 1) do
begin
DragQueryFile(Message.Drop, i, @Buffer, SizeOf(Buffer));
Form1.Memo1.Lines.Add(Buffer);
end;
end;

파일복사

procedure FileCopy( const SrcFile, TarFile: string );
begin
try
CopyFile(PChar(SrcFile),PChar(TarFile),false);
except
end;
end;

// File_Copy(ed_ReadFn.Text, ed_saveFloder.Text);
function File_Copy(const sSrcFile, sTarFile: string; pro: TProgressBar): Integer;
var
SplitSize, ReadSize, iFileSize, iFilePos: integer;
readFn, writeFn: string;
fReadHdl, fWriteHdl: THandle;
fModified: TFileTime;
buffer: pchar;
begin
SplitSize := 1;
// if SplitSize < minAllowedSplitSize then exit; //something wrong!!
SplitSize := SplitSize*1024; //nb: was in Kb's

//get the name of the file to split...
readFn := sSrcFile;
if not fileexists(readFn) then
begin
result:= 1; //'File not Found...'
exit; //something wrong!!
end;

//get the 'target' folder (where split files are to be saved) ...
writeFn := sTarFile;

GetMem(buffer,SplitSize);
if buffer = nil then
begin
result:= 3; //'Out of Memory...';
exit; //something wrong!!
end;

try
//StatusBar1.SimpleText:= 'Splitting Files';
//Open source file for reading...
fReadHdl := FileOpen(readFn, fmOpenRead or fmShareDenyNone);
if fReadHdl < 1 then
begin
result:= 4; //'Can''t Open File...';
exit; //something wrong!!
end;
iFileSize:= GetFileSize(fReadHdl, nil);
if pro <> nil then
pro.Max:= iFileSize;
try
//get the checksum and write it to file...
//StatusBar1.SimpleText:= 'Creation Check sum';
// Checksum := GetChecksum(fReadHdl);
//cancel if escape pressed while getting Checksum...

//get the original file's datetime...
GetFileTime(fReadHdl,nil,nil,@fModified);

//top of loop /////////////////////////////////
fWriteHdl := FileCreate(sTarFile);
if fWriteHdl < 1 then
begin
result:= 5; //'Can''t Create File';
exit; //something wrong!!
end;
try
iFilePos:= 0;
repeat
//StatusBar1.SimpleText:= 'Splitting Files ' + inttostr(cnt);
ReadSize := FileRead(fReadHdl, Buffer^, SplitSize);
iFilePos:= iFilePos + ReadSize;
if pro <> nil then
begin
pro.Position:= iFilePos;
pro.Repaint;
end;
FileWrite(fWriteHdl, Buffer^, ReadSize);
until (ReadSize <> SplitSize);
//set to the original file's datetime...
SetFileTime(fWriteHdl,nil,nil,@fModified);
finally
FileClose(fWriteHdl);
end;
//bottom of loop //////////////////////////////
finally
FileClose(fReadHdl);
end;
finally
FreeMem(Buffer);
end;
result:= 0;
end;

화일 split / join

//전체소스

unitSplitJoin;

interface

uses
Windows,Messages,SysUtils,Variants,Classes,Dialogs,CommCtrl,CommDlg,
ShlObj,ShellApi,Mask,ComCtrls;

functionSplitFiles(constsFileName,sFolder:string;iSplitSize:Integer):Integer;Export;Stdcall;
functionJoinFiles(constsSaveFileName:string;sSplitFileName:TStrings;constbDeleteFile:boolean):Integer;Export;Stdcall;

implementation

//GetLongFilename()isreallyonlyneededwhenfilesaredropped
//ontotheSplitJoin.exeiconinExplorer,asExplorerusesthe
//8.3filenameformatinthecommandline...
functionGetLongFilename(constfn:string):string;
var
desktop:IShellFolder;
OlePath:array[0..MAX_PATH]ofWideChar;
pidl:PItemIDList;
dummy1,dummy2:ULONG;
StrRet:TStrRet;
begin
result:=fn;
if(length(fn)<4)or(fn[2]<>':')thenexit;
ifSHGetDesktopFolder(desktop)<>NOERRORthenexit;
StringToWideChar(fn,OlePath,MAX_PATH);
ifdesktop.ParseDisplayName(0,nil,OlePath,dummy1,pidl,dummy2)<>NOERRORthen
exit;
ifdesktop.GetDisplayNameOf(pidl,SHGDN_FORPARSING,StrRet)<>NOERRORthen
exit;
caseStrRet.uTypeof
STRRET_WSTR:Result:=WideCharToString(StrRet.pOleStr);
STRRET_OFFSET:Result:=PChar(UINT(Pidl)+StrRet.uOffset);
STRRET_CSTR:Result:=StrRet.cStr;
End;
end;
//--------------------------------------------------------------------------

functionDirectoryExists(constName:string):Boolean;
var
Code:Integer;
begin
Code:=GetFileAttributes(PChar(Name));
Result:=(Code<>-1)and(FILE_ATTRIBUTE_DIRECTORYandCode<>0);
end;
//--------------------------------------------------------------------------

//Toenablethe<Escape>keytostopsplittingorjoining...
functionEscapePressed:boolean;
var
Msg:TMsg;
begin
whilePeekMessage(Msg,0,WM_KEYDOWN,WM_KEYDOWN,PM_REMOVE)do
if(Msg.wParam=VK_ESCAPE)then
begin
//Form1.StatusBar1.SimpleText:='Cenceled';
result:=true;
exit;
end;
result:=false;
end;
//--------------------------------------------------------------------------

const
table:ARRAY[0..255]OFDWORD=
($00000000,$77073096,$EE0E612C,$990951BA,
$076DC419,$706AF48F,$E963A535,$9E6495A3,
$0EDB8832,$79DCB8A4,$E0D5E91E,$97D2D988,
$09B64C2B,$7EB17CBD,$E7B82D07,$90BF1D91,
$1DB71064,$6AB020F2,$F3B97148,$84BE41DE,
$1ADAD47D,$6DDDE4EB,$F4D4B551,$83D385C7,
$136C9856,$646BA8C0,$FD62F97A,$8A65C9EC,
$14015C4F,$63066CD9,$FA0F3D63,$8D080DF5,
$3B6E20C8,$4C69105E,$D56041E4,$A2677172,
$3C03E4D1,$4B04D447,$D20D85FD,$A50AB56B,
$35B5A8FA,$42B2986C,$DBBBC9D6,$ACBCF940,
$32D86CE3,$45DF5C75,$DCD60DCF,$ABD13D59,
$26D930AC,$51DE003A,$C8D75180,$BFD06116,
$21B4F4B5,$56B3C423,$CFBA9599,$B8BDA50F,
$2802B89E,$5F058808,$C60CD9B2,$B10BE924,
$2F6F7C87,$58684C11,$C1611DAB,$B6662D3D,

$76DC4190,$01DB7106,$98D220BC,$EFD5102A,
$71B18589,$06B6B51F,$9FBFE4A5,$E8B8D433,
$7807C9A2,$0F00F934,$9609A88E,$E10E9818,
$7F6A0DBB,$086D3D2D,$91646C97,$E6635C01,
$6B6B51F4,$1C6C6162,$856530D8,$F262004E,
$6C0695ED,$1B01A57B,$8208F4C1,$F50FC457,
$65B0D9C6,$12B7E950,$8BBEB8EA,$FCB9887C,
$62DD1DDF,$15DA2D49,$8CD37CF3,$FBD44C65,
$4DB26158,$3AB551CE,$A3BC0074,$D4BB30E2,
$4ADFA541,$3DD895D7,$A4D1C46D,$D3D6F4FB,
$4369E96A,$346ED9FC,$AD678846,$DA60B8D0,
$44042D73,$33031DE5,$AA0A4C5F,$DD0D7CC9,
$5005713C,$270241AA,$BE0B1010,$C90C2086,
$5768B525,$206F85B3,$B966D409,$CE61E49F,
$5EDEF90E,$29D9C998,$B0D09822,$C7D7A8B4,
$59B33D17,$2EB40D81,$B7BD5C3B,$C0BA6CAD,

$EDB88320,$9ABFB3B6,$03B6E20C,$74B1D29A,
$EAD54739,$9DD277AF,$04DB2615,$73DC1683,
$E3630B12,$94643B84,$0D6D6A3E,$7A6A5AA8,
$E40ECF0B,$9309FF9D,$0A00AE27,$7D079EB1,
$F00F9344,$8708A3D2,$1E01F268,$6906C2FE,
$F762575D,$806567CB,$196C3671,$6E6B06E7,
$FED41B76,$89D32BE0,$10DA7A5A,$67DD4ACC,
$F9B9DF6F,$8EBEEFF9,$17B7BE43,$60B08ED5,
$D6D6A3E8,$A1D1937E,$38D8C2C4,$4FDFF252,
$D1BB67F1,$A6BC5767,$3FB506DD,$48B2364B,
$D80D2BDA,$AF0A1B4C,$36034AF6,$41047A60,
$DF60EFC3,$A867DF55,$316E8EEF,$4669BE79,
$CB61B38C,$BC66831A,$256FD2A0,$5268E236,
$CC0C7795,$BB0B4703,$220216B9,$5505262F,
$C5BA3BBE,$B2BD0B28,$2BB45A92,$5CB36A04,
$C2D7FFA7,$B5D0CF31,$2CD99E8B,$5BDEAE1D,

$9B64C2B0,$EC63F226,$756AA39C,$026D930A,
$9C0906A9,$EB0E363F,$72076785,$05005713,
$95BF4A82,$E2B87A14,$7BB12BAE,$0CB61B38,
$92D28E9B,$E5D5BE0D,$7CDCEFB7,$0BDBDF21,
$86D3D2D4,$F1D4E242,$68DDB3F8,$1FDA836E,
$81BE16CD,$F6B9265B,$6FB077E1,$18B74777,
$88085AE6,$FF0F6A70,$66063BCA,$11010B5C,
$8F659EFF,$F862AE69,$616BFFD3,$166CCF45,
$A00AE278,$D70DD2EE,$4E048354,$3903B3C2,
$A7672661,$D06016F7,$4969474D,$3E6E77DB,
$AED16A4A,$D9D65ADC,$40DF0B66,$37D83BF0,
$A9BCAE53,$DEBB9EC5,$47B2CF7F,$30B5FFE9,
$BDBDF21C,$CABAC28A,$53B39330,$24B4A3A6,
$BAD03605,$CDD70693,$54DE5729,$23D967BF,
$B3667A2E,$C4614AB8,$5D681B02,$2A6F2B94,
$B40BBE37,$C30C8EA1,$5A05DF1B,$2D02EF8D);

//PKZipcompliant32bitCRCalgorithm
//AlgorithmcourtesyofEarlF.Glynn,andusedwithhiskindpermission...
//(http://www.efg2.com/Lab/Mathematics/CRC.htm)
functionCalcCRC32(p:pointer;ByteCount:dword):dword;
var
i:dword;
q:Pbyte;
begin
q:=p;
result:=$FFFFFFFF;
fori:=0toByteCount-1do
begin
result:=(resultshr8)xortable[q^xor(resultand$000000ff)];
inc(q);

//checkifescapepressedaftereachMbparsed...
//thisslowsthealgorithmalittlebutisnecessarytoallowtheuserto
//breakoutofthisfunctionasitmaytakesometimewithverylargefiles
if(imod$100000=0)andEscapePressedthen
begin
result:=$FFFFFFFF;
exit;
end;

end;
result:=notresult;
end;
//--------------------------------------------------------------------------

functionGetChecksum(constFileHandle:THandle):DWORD;
var
mapHdl:THandle;
memPtr:Pointer;
begin
result:=$FFFFFFFF;//ie:assumeerror
memPtr:=nil;
mapHdl:=0;
try
mapHdl:=CreateFileMapping(FileHandle,nil,PAGE_READONLY,0,0,nil);
ifmapHdl=0thenexit;
memPtr:=MapViewOfFile(mapHdl,FILE_MAP_READ,0,0,0);
ifmemPtr=nilthenexit;
result:=CalcCRC32(memPtr,GetFileSize(FileHandle,nil));
finally
ifAssigned(memPtr)thenUnmapViewOfFile(memPtr);
ifmapHdl<>0thenCloseHandle(mapHdl);
end;
end;

//---------------------------------------------------------------------
//CallfunctionSyntax
//
//vari:integer;
//begin
//i:=SplitFiles(ed_ReadFn.Text,ed_saveFloder.Text,StrToIntDef(ed_SplitSize.Text,0));
//caseiof
//0:StatusBar1.SimpleText:='SplitFinished';
//1:StatusBar1.SimpleText:='FilenotFound...';
//2:StatusBar1.SimpleText:='FoldernotFound...';
//3:StatusBar1.SimpleText:='OutofMemory...';
//4:StatusBar1.SimpleText:='Can''tOpenFile...';
//5:StatusBar1.SimpleText:='Can''tCreateFile';
//6:StatusBar1.SimpleText:='SplitFileSizeError';
//end;
functionSplitFiles(constsFileName,sFolder:string;iSplitSize:Integer):Integer;
var
cnt,SplitSize,ReadSize:integer;
Checksum:dword;
readFn,writeFn,splitFn:string;
fReadHdl,fWriteHdl:THandle;
fModified:TFileTime;
buffer:pchar;
begin
result:=0;
SplitSize:=iSplitSize;
//ifSplitSize<minAllowedSplitSizethenexit;//somethingwrong!!
ifSplitSize<5then
begin
result:=6;
exit;//somethingwrong!!
end;
SplitSize:=SplitSize*1024;//nb:wasinKb's

//getthenameofthefiletosplit...
readFn:=sFileName;
ifnotfileexists(readFn)then
begin
result:=1;//'FilenotFound...'
exit;//somethingwrong!!
end;

//getthe'target'folder(wheresplitfilesaretobesaved)...
writeFn:=sFolder;
ifnotdirectoryexists(writeFn)then
begin
result:=2;//'FoldernotFound...'
exit;//somethingwrong!!
end;
ifwriteFn[length(writeFn)]<>'\'thenwriteFn:=writeFn+'\';
//appendfilenametothetargetfolder...
writeFn:=writeFn+extractfilename(readFn);


GetMem(buffer,SplitSize);
ifbuffer=nilthen
begin
result:=3;//'OutofMemory...';
exit;//somethingwrong!!
end;

try
//StatusBar1.SimpleText:='SplittingFiles';
//Opensourcefileforreading...
fReadHdl:=FileOpen(readFn,fmOpenReadorfmShareDenyNone);
iffReadHdl<1then
begin
result:=4;//'Can''tOpenFile...';
exit;//somethingwrong!!
end;

try
//getthechecksumandwriteittofile...
//StatusBar1.SimpleText:='CreationChecksum';
Checksum:=GetChecksum(fReadHdl);
//cancelifescapepressedwhilegettingChecksum...
ifChecksum=$FFFFFFFFthenexit;
fWriteHdl:=FileCreate(writeFn+'.999');
iffWriteHdl>0then
try
FileWrite(fWriteHdl,Checksum,sizeof(Checksum));
finally
FileClose(fWriteHdl);
end;

//gettheoriginalfile'sdatetime...
GetFileTime(fReadHdl,nil,nil,@fModified);

cnt:=1;
//topofloop/////////////////////////////////
repeat
//StatusBar1.SimpleText:='SplittingFiles'+inttostr(cnt);
ReadSize:=FileRead(fReadHdl,Buffer^,SplitSize);
splitFn:=writeFn+format('.%3.3d',[cnt]);
fWriteHdl:=FileCreate(splitFn);
iffWriteHdl<1then
begin
result:=5;//'Can''tCreateFile';
exit;//somethingwrong!!
end;
try
FileWrite(fWriteHdl,Buffer^,ReadSize);
//settotheoriginalfile'sdatetime...
SetFileTime(fWriteHdl,nil,nil,@fModified);
finally
FileClose(fWriteHdl);
end;
inc(cnt);

ifEscapePressedthenexit;
until(ReadSize<>SplitSize);
//bottomofloop//////////////////////////////
finally
FileClose(fReadHdl);
end;
finally
FreeMem(Buffer);
end;
result:=0;
end;

//--------------------------------------------------------------------------
//CallfunctionSyntax
//
//vari:integer;
//begin
//i:=JoinFiles(ed_saveFile.Text,ed_FileList.Lines,ed_DeleteFile.Checked);
//caseiof
//0:StatusBar1.SimpleText:='JoinFinished';
//1:StatusBar1.SimpleText:='Can''tCreateFile';
//2:StatusBar1.SimpleText:='JoiningFiles';
//3:StatusBar1.SimpleText:='Can''tOpenFile';
//4:StatusBar1.SimpleText:='Can''tReadWriteFile';
//5:StatusBar1.SimpleText:='ChecksumFail';
//end;
functionJoinFiles(constsSaveFileName:string;sSplitFileName:TStrings;constbDeleteFile:Boolean):Integer;
var
cnt,FileSize,ReadSize,cntTotal:integer;
OldChecksum,NewChecksum:dword;
readFn,writeFn:string;
fReadHdl,fWriteHdl:THandle;
fModified:TFileTime;
buffer:pchar;
joinSize:integer;
begin
//getthefilenameforthenewfile...
writeFn:=sSaveFileName;
//createthenewfilereadyforwriting...
fWriteHdl:=FileCreate(writeFn);
iffWriteHdl<1then
begin
result:=1;//'Can''tCreateFile';
exit;//somethingwrong!!
end;

buffer:=nil;
try
cntTotal:=sSplitFileName.Count;
cnt:=0;
joinSize:=0;
result:=2;
//topofloop/////////////////////////////////
while(cnt<cntTotal)do
begin
//StatusBar1.SimpleText:='JoiningFilesCenceled'+IntToStr(cnt+1);
//geteachfilenamepartfromthelist...
readFn:=sSplitFileName[cnt];
ifreadFn=''thenbreak;
readFn:=readFn;
fReadHdl:=FileOpen(readFn,fmOpenReadorfmShareDenyNone);
iffReadHdl<1then
begin
result:=3;//'Can''tOpenFile';
exit;//somethingwrong!!
end;
//now,copythisfile...
try
//getthefirstfilepart'sdatetime...
ifcnt=0thenGetFileTime(fReadHdl,nil,nil,@fModified);

FileSize:=Windows.GetFileSize(fReadHdl,nil);
inc(joinSize,FileSize);
ReAllocMem(buffer,FileSize);
ifbuffer=nilthenbreak;
ReadSize:=FileRead(fReadHdl,Buffer^,FileSize);
ifReadSize<>FileSizethenbreak;
ifFileWrite(fWriteHdl,Buffer^,FileSize)<>FileSizethenbreak;
ifEscapePressedthenexit;
finally
FileClose(fReadHdl);
end;
inc(cnt);
end;
//bottomofloop//////////////////////////////

//checkforerrorswhilereading/writingfiles(see'breaks'above)...
ifdword(joinSize)<>Windows.GetFileSize(fWriteHdl,nil)then
begin
result:=4;//'Can''tReadWriteFile'
exit;//badcopy!!!
end;

//verifychecksumifpresent...
//(itwontbepresentifjoiningfilessplitbyanotherutility)
readFn:=changefileext(readFn,'.999');
iffileexists(readFn)then
begin
//result:=5;//'ChekcingChecksum';
NewChecksum:=GetChecksum(fWriteHdl);

ifnot(NewChecksum=$FFFFFFFF)then//usercancelledchecksumcalc
begin
fReadHdl:=FileOpen(readFn,fmOpenReadorfmShareDenyNone);
iffReadHdl>0then
try
ifFileRead(fReadHdl,OldChecksum,sizeof(OldChecksum))=
sizeof(OldChecksum)then
ifnot(NewChecksum=OldChecksum)then
begin
result:=5;//ChecksumFail
exit;//badchecksum!!!
end;
finally
FileClose(fReadHdl);
end;
end;
end;

//restorethefile'soriginalDateTime...
SetFileTime(fWriteHdl,nil,nil,@fModified);
finally
FileClose(fWriteHdl);
FreeMem(buffer);
end;
result:=0;
//deleteallfilepartsifcheckboxticked...
ifbDeleteFilethen
begin
//nb:readFnstill=Checksumfileatthispoint...
iffileexists(readFn)thenDeleteFile(readFn);
cnt:=0;
//topofloop/////////////////////////////////
whilecnt<cntTotaldo
begin
//geteachfilenameinthelist...
readFn:=sSplitFileName[cnt];
ifreadFn=''thenbreak;
DeleteFile(readFn);
inc(cnt);
end;
//bottomofloop//////////////////////////////
end;
end;

짤은 화일명알기

function GetShortName( sLongName : string ) : string;
var
sShortName : string;
nShortNameLen : integer;
begin
SetLength( sShortName, MAX_PATH );
nShortNameLen := GetShortPathName(PChar( sLongName ), PChar( sShortName ), MAX_PATH - 1 );

if( 0 = nShortNameLen )then
begin
// handle errors...
end;

SetLength( sShortName, nShortNameLen );

Result := sShortName;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Edit2.Text := GetShortName(Edit1.Text);
end;

자기자신실행화일 삭제하기

procedure DeleteMe;
var
BatchFile: TextFile;
BatchFileName: string;
ProcessInfo: TProcessInformation;
StartUpInfo: TStartupInfo;
begin
{ create a batchfile in the applications directory }
BatchFileName := ExtractFilePath(ParamStr(0)) + '$$336699.bat';

{ open and write the file }
AssignFile(BatchFile, BatchFileName);
Rewrite(BatchFile);

Writeln(BatchFile, ':try');
Writeln(BatchFile, 'del "' + ParamStr(0) + '"');
Writeln(BatchFile,
'if exist "' + ParamStr(0) + '"' + ' goto try');
Writeln(BatchFile, 'del "' + BatchFileName + '"');
CloseFile(BatchFile);

FillChar(StartUpInfo, SizeOf(StartUpInfo), $00);
StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;
StartUpInfo.wShowWindow := SW_HIDE;

if CreateProcess(nil, PChar(BatchFileName), nil, nil,
False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo,
ProcessInfo) then
begin
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
end;
end;

외부 프로그램 위치 이동하기

procedure TFrm_wiseFNUpdateMain.Fnwindowpos;
var WinPlac: TWindowPlacement;
iRight, iBottom: Integer;
begin
H:= FindWindow('TfrmValuewise',nil);
if (H > 0) and IsWindowVisible(H) then
begin
FillChar(WinPlac, SizeOf(WinPlac), 0);
WinPlac.length := SizeOf(WinPlac);
GetWindowPlacement(H, @WinPlac);
// 윈도우즈가 표준상태일때의 좌표를 구한다
iRight := WinPlac.rcNormalPosition.Right - WinPlac.rcNormalPosition.Left;
iBottom:= WinPlac.rcNormalPosition.Bottom - WinPlac.rcNormalPosition.Top;

WinPlac.rcNormalPosition.Left:= 0;
WinPlac.rcNormalPosition.Top := 0;
WinPlac.rcNormalPosition.Right := iRight;
WinPlac.rcNormalPosition.Bottom:= iBottom;

SetWindowPlacement(H, @WinPlac);
end;
Memo1.Lines.Add('프로그램 위치조정');
end;

실행화일에서 아이콘 가지고 오기

var hinstance: HINST;
begin
image1.Picture.Icon.handle := ExtractIcon(hinstance, 'notepad.exe', 0);
end;

실행화일에 PATH알기

ShowMessage(ExtractFilePath(Application.ExeName));

실행시 화일이름변경

ReNameFile(Application.ExeName, ExtractFilePath(Application.ExeName) + '라라라.exe');

바탕화면에 그림설정하기

var
s: string;
begin
if OpenDialog1.Execute then
s := OpenDialog1.FileName;
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, PChar(s), 0)

ProgressBar사용 화일복사

procedure FileCopy(fn1, fn2: string; Bar: TProgressBar);
var
iBuffer,iCount: LongInt;
F,TF: Integer;
iFileLength: Int64;
iCnt: Int64;
begin
iBuffer:= 0; iCount:= 1;
F:= FileOpen(PChar(Fn1),fmOpenRead);
TF:= FileCreate(Fn2);
try
iFileLength := FileSeek(F,Int64(0),2);
Bar.Max:= iFileLength;
FileSeek(F,0,0);
iCnt:= 0;
while iFileLength > iCnt do begin
FileRead(F, iBuffer, iCount);
FileWrite(TF,iBuffer,iCount);
Bar.Position:= iCnt;
iCnt:= FileSeek(F,Int64(0),1);
end;
finally
FileClose(F);
FileClose(TF);
end;
end;

자기 자신을 지우는 프로그램 만들기

from. 나이렉스 홈페이지 팁란( <a href='http://www.nilex.net/ target='_blank'>http://www.nilex.net/</a> )
안치봉( <a href='mailto:ahn@nilex.co.kr' target='_blank'>ahn@nilex.co.kr</a> )
자기 자신을 지우는 프로그램은 대부분 인스톨에 관계된것 중에서 Uninstall 프로그램
에 적용이 됩니다. 아래는 그 소스입니다. 간단히 설명을 드리자면 원래 실행중인 프
로그램을 당장(?) 삭제하는것은 힘듭니다. 그래서 아래꽁수는 시스템에서 지원해주는
기능을 사용합니다. 자세한건 소스를 직접 분석해 보시기 바랍니다 - 백문이 불여 일
행!

...
...

procedure TForm1.RemoveFile(FileName: String);
var
ShortDest: array[0..400] of Char;
WINInit: TINIFile;
begin
case GetWindowsVerType of
wvWin95: begin
WINInit := TINIFile.Create('WININIT.INI');
try
GetShortPathName(PChar(FileName),ShortDest,SizeOf(ShortDest));
WINInit.WriteString('Rename','nul',StrPas(ShortDest));
finally
WINInit.Free;
end;
end;
else
MoveFileEx(PChar(FileName),Nil,MOVEFILE_REPLACE_EXISTING or MOVEFILE_DELAY_U
NTIL_REBOOT);
end;
end;

function TForm1.GetWindowsVerType: TWindowsVerType;
var
OSVersionInfo: TOSVersionInfo;
Version: String;
begin
Result := wvUnidentified;
OSVersionInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
if not GetVersionEx(OSVersionInfo) then
raise Exception.Create('Could not get information about the current version
of Windows');
Version := IntToStr(OSVersionInfo.dwMajorVersion)+'.'+IntToStr(OSVersionInfo.d
wMinorVersion);
case OSVersionInfo.dwPlatformId of
VER_PLATFORM_WIN32s: Result := wv31Win32;
VER_PLATFORM_WIN32_WINDOWS: Result := wvWin95;
VER_PLATFORM_WIN32_NT: begin
if Pos('3.5',Version) > 0 then
Result := wvWinNT351
else
Result := wvWinNT;
end;
else
Result := wvUnidentified;
end;
end;

찾지말고 통 하자!

TStringGrid에 Excel내용을 복사/붙여넣기

//전체 소스

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, Grids, StdCtrls,

Clipbrd; //추가

type
TForm1 = class(TForm)
StringGrid1: TStringGrid;
procedure StringGrid1KeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
private
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

type TPGrid = class(TStringGrid);

procedure TForm1.StringGrid1KeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
const cRETURN1 = #$D;
cRETURN2 = #$A;
cTAB = #9;
var
Value: string;
Str: string;
i, iCol, iRow: Integer;
begin
Edit1.Text:= IntToStr(Key);
if (Shift = [ssCtrl]) and (Key = 67) then //Copy
begin
Str:= '';
with StringGrid1 do
for i:= 1 to ColCount - 1 do
Str:= Str + Cells[i,Row] + cTAB;
Str:= Copy(Str,1,Length(Str)-1);
Clipboard.Open;
Clipboard.AsText:= Str;
Clipboard.Close;
end else
if (Shift = [ssCtrl]) and (Key = 86) then //Paste
begin
Clipboard.Open;
if not Clipboard.HasFormat(CF_Text) then Exit;
Value := Clipboard.AsText;
Clipboard.Close;
with TPGrid(StringGrid1) do
begin
iCol:= Col;
iRow:= Row;
Cells[iCol, iRow]:= '';
for i:= 1 to Length(Value) do begin
if Copy(Value,i,1) = cRETURN1 then Continue;
if Copy(Value,i,1) = cRETURN2 then begin
iCol:= Col;
Inc(iRow);
if i < Length(Value) then Cells[iCol, iRow]:= '';
Continue;
end;
if Copy(Value,i,1) = cTAB then begin
Inc(iCol);
if i < Length(Value) then Cells[iCol, iRow]:= '';
Continue;
end;
Cells[iCol,iRow]:= Cells[iCol,iRow] + Copy(Value,i,1);
end;
if RowCount - 1 < iRow then RowCount:= iRow;
if InplaceEditor = nil then Exit;
InplaceEditor.Text:= Cells[Col, Row];
InplaceEditor.SelStart:= Length(Cells[Col, Row]);
Edit1.Text:= InplaceEditor.Text;
end;
end;
end;

end.

TStringGrid에서 TCheckBox사용하기

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, Grids, StdCtrls;

type
TForm1 = class(TForm)
StringGrid1: TStringGrid;
procedure StringGrid1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure DrawCheck(ACanvas: TCanvas; ARect: TRect; AColor: TColor; EditStyle: word; Flag: string);
var iDR:integer;
begin
if Trim(Flag) = '' then Exit;
with ACanvas do
begin
case EditStyle of
1: begin //esCheckBox
case Flag[1] of
'1': iDR:= DFCS_BUTTONCHECK or DFCS_BUTTON3STATE;
'2': iDR:= DFCS_BUTTONCHECK or DFCS_CHECKED;
'3': iDR:= DFCS_BUTTONCHECK or DFCS_BUTTON3STATE or DFCS_INACTIVE;
'4': iDR:= DFCS_BUTTONCHECK or DFCS_BUTTON3STATE or DFCS_INACTIVE or DFCS_CHECKED;
else iDR:= DFCS_BUTTONCHECK or DFCS_BUTTON3STATE;
end;
end;
2: begin //esRadioButton
case Flag[1] of
'1': iDR:= DFCS_BUTTONRADIO;
'2': iDR:= DFCS_BUTTONRADIO or DFCS_CHECKED;
'3': iDR:= DFCS_BUTTONRADIO or DFCS_INACTIVE;
'4': iDR:= DFCS_BUTTONRADIO or DFCS_CHECKED or DFCS_INACTIVE;
else iDR:= DFCS_BUTTONRADIO;
end;
end;
else Exit;
end;
ACanvas.Brush.Color:= AColor;
ACanvas.FillRect(ARect);
InflateRect(ARect,-((ARect.Right - ARect.Left -14) shr 1),-((ARect.Bottom - ARect.Top -14) shr 1)); //DFCS_MONO
DrawFrameControl(Handle, ARect, DFC_BUTTON, iDR);
end;
end;

var ACol,ARow: Integer;

procedure TForm1.StringGrid1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft Then
StringGrid1.MouseToCell(X, Y, ACol, ARow);
end;

procedure TForm1.StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var iCol,iRow: Integer;
begin
if Button = mbLeft Then
with StringGrid1 do
begin
MouseToCell(X, Y, iCol, iRow);
if (ACol = 1) and (ARow > 0) and (ACol = iCol) and (ARow = iRow) then
Cells[ACol, ARow]:= IntToStr(StrToIntDef(Cells[ACol, ARow],0) mod 2 + 1);
end;
end;

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
begin
if (ACol = 1) and (ARow > 0) then
with StringGrid1 do DrawCheck(Canvas,Rect, Color,1, Cells[ACol, ARow]);
end;

procedure TForm1.FormCreate(Sender: TObject);
var i: integer;
begin
with StringGrid1 do
for i:= 1 to RowCount - 1 do
Cells[1,i]:= '1';
end;

end.

TStringGrid에서 Sort기능


//Sort함수 PGrid = 정렬한 TStringGrid, aCol = 정렬한 Col값
procedure Sort(PGrid: TStringGrid; aCol: LongInt);

procedure QuickSort(PGrid: TPGrid; aCol, iLo, iHi: LongInt);
var Lo, Hi: LongInt;
Mid: string;
begin
with PGrid do
begin
Lo := iLo;
Hi := iHi;
Mid:= Cells[aCol,(Lo + Hi) div 2];
repeat
while Cells[aCol, Lo] < Mid do Inc(Lo);
while Cells[aCol, Hi] > Mid do Dec(Hi);
if Lo <= Hi then
begin
RowMoved(Lo, Hi);
//Lo번째 로우(Row)를 Hi번째 로우로 이동한다.
if Hi <> Lo then
RowMoved(Hi-1, Lo);
Inc(Lo);Dec(Hi);
end;
until Lo > Hi;
if Hi > iLo then
QuickSort(PGrid, aCol, iLo, Hi);
if Lo < iHi then
QuickSort(PGrid, aCol, Lo, iHi);
end;
end;

사용 예) QuickSort(TPGrid(PGrid), aCol, 1, PGrid.RowCount);

TStringGrid에서 포커스색상 지우기


//DrawCell이벤트에서 처리
with (Sender as TStringGrid), (Sender as TStringGrid).Canvas do

begin
if (ACol >= FixedCols) and (ARow >= FixedRows) then begin
Brush.Color:= (Sender as TStringGrid).Color;
FillRect(Rect);
TextOut(Rect.Left, Rect.Top, Cells[ACol, ARow]);
end;
end;

StringGrid에 두줄 사용

--서론 --
델마당에 질문이 있기에 제가 대답하고 발행합니다.
StringGrid를 사용하다보면 타이틀을 두줄로 표시해야하는 경우가 있습니다.
그런 경우는 OnDrawCell이벤트에서 TRect값을 받아서 위치를 변경하여 처리하면 됩니다.

--내용 --

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
var
ipos: integer;
begin
with TStringGrid(Sender), TStringGrid(Sender).Canvas do
if Pos('@',Cells[ACol,ARow]) > 0 then begin //@는 구분자로 사용됩
ipos:= Pos('@',Cells[ACol,ARow]);
FillRect(Rect);
TextOut(Rect.Left+ 3, Rect.Top+3, copy(Cells[ACol,ARow], 1, ipos - 1));
TextOut(Rect.Left+ 3, Rect.Top+20, copy(Cells[ACol,ARow],ipos + 1, Length(Cells[ACol,ARow])));
end;
end;


StringGrid관련 함수들

type TRowGrid = class(TStringGrid) end;

procedure InsertRow(Sender:TStringGrid);
begin
with TRowGrid(Sender) do
begin
RowMoved(RowCount, Row);
RowCount:= RowCount + 1;
end;
end;

procedure DeleteRow(Sender:TStringGrid);
begin
with TRowGrid(Sender) do
begin
Rows[Row].Clear;
RowMoved(Row, RowCount);
if (FixedRows + 1) < RowCount then
RowCount:= RowCount - 1;
end;
end;

procedure ClearData(Sender:TStringGrid);
var i: integer;
begin
with Sender do
begin
for i:= 1 to RowCount - 1 do
Rows[i].Clear;
RowCount:= 2;
end;
end;

procedure WriteText(ACanvas: TCanvas; ARect: TRect; Text: string; AFont: TFont; AColor: TColor; Align: TCellAlign);
var Left,Top: Integer;
begin
case Align of
AlLeft : Left := ARect.Left + 2;
AlRight: Left := ARect.Right - ACanvas.TextWidth(Text) - 3;
else
Left := ARect.Left + (ARect.Right - ARect.Left) shr 1
- (ACanvas.TextWidth(Text) shr 1);
end;
Top := ARect.Top + (ARect.Bottom - ARect.Top) shr 1
- (ACanvas.TextHeight(Text) shr 1) + 1;
ACanvas.Brush.Color:= AColor;
ACanvas.Font.Assign(AFont);
ExtTextOut(ACanvas.Handle, Left, Top, ETO_OPAQUE or ETO_CLIPPED, @ARect, PChar(Text), Length(Text), nil);
end;

StringGrid 그림을 표시하기

function GraphicRect(Rect: TRect; Graphic: TGraphic): TRect;
var GRect: TRect;
SrcRatio, DstRatio: double;
H, W: Integer;
begin
GRect:= Rect;
GRect.Left:= GRect.Left+1;
GRect.Top:= GRect.Top+1 ;
GRect.Right:= GRect.Right-1;
GRect.Bottom:= GRect.Bottom-1;
result:= GRect;
if (Graphic.Width < Rect.Right - Rect.Left)
and (Graphic.Height < Rect.Bottom - Rect.Top) then
begin
GRect:= Rect;
GRect.Left:= GRect.Left + ((GRect.Right - GRect.Left) shr 1) - Graphic.Width shr 1;
GRect.Right:= GRect.Left + Graphic.Width;
GRect.Top:= GRect.Top + ((GRect.Bottom - GRect.Top) shr 1) - Graphic.Height shr 1;
GRect.Bottom:= GRect.Top + Graphic.Height;
end else begin
with Graphic do SrcRatio := Width / Height;
with GRect do DstRatio := (Right - Left) / (Bottom - Top);

if SrcRatio > DstRatio
then with GRect do begin
h := trunc((Right - Left) / SrcRatio);
with GRect do begin
Top := (Top + Bottom) div 2 - h div 2;
Bottom := Top + h;
end;
end else
if SrcRatio < DstRatio then begin
with GRect do begin
w := trunc((Bottom - Top) * SrcRatio);
with GRect do begin
Left := (Left + Right) div 2 - w div 2;
Right := Left + w;
end;
end;
end;
end;
result:= GRect;
end;

procedure TForm2.HyperGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
var Graphic: TGraphic;
B: TBitMap;
begin
with TStringGrid(Sender) do
if (ACol = 2) and (ARow = 1) then
begin
Graphic:= Image1.Picture.Graphic;
Rect:= GraphicRect(Rect,Graphic);
Canvas.StretchDraw( Rect, Graphic );
end else
if (ACol = 1) and (ARow > 0) then
begin
b:= TBitMap.Create;
try
ImageList1.GetBitmap(StrToIntDef(Cells[ACol,ARow],0),B);
Graphic:= B;
Rect:= GraphicRect(Rect,Graphic);
Canvas.StretchDraw( Rect, Graphic );
finally
b.Free;
end;
end;
end;

procedure TForm2.HyperGrid1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
with HyperGrid1 do begin
if Col = 1 then begin
Cells[1,Row]:= IntToStr((StrToIntDef(Cells[1,Row],0) + 1) mod 2);
end;
end;
end;

dbgrid 에서 drag and drop

// DBGrid 에서 는 MouseDown 이벤트를 그냥 상속하면
// 마우스 이벤트가 발생하지 않는다.
// 아래와 같이 MouseDown 이벤트를 발생시키는
// 새로운 DBGrid 컴포넌트를 만들어야 한다.

-----------------
The MyDBGrid unit
-----------------

unit MyDBGrid;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, Grids, DBGrids;

type
TMyDBGrid = class(TDBGrid)
private
{ Private declarations }
FOnMouseDown: TMouseEvent;
protected
{ Protected declarations }
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
published
{ Published declarations }
property Row;
property OnMouseDown read FOnMouseDown write FOnMouseDown;
end;

procedure Register;

implementation

procedure TMyDBGrid.MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Assigned(FOnMouseDown) then
FOnMouseDown(Self, Button, Shift, X, Y);
inherited MouseDown(Button, Shift, X, Y);
end;

procedure Register;
begin
RegisterComponents('Samples', [TMyDBGrid]);
end;

end.

// 다음은 프로그램 예제이다
---------------
The GridU1 unit
---------------

unit GridU1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, Db, DBTables, Grids, DBGrids, MyDBGrid, StdCtrls;

type
TForm1 = class(TForm)
MyDBGrid1: TMyDBGrid;
Table1: TTable;
DataSource1: TDataSource;
Table2: TTable;
DataSource2: TDataSource;
MyDBGrid2: TMyDBGrid;
procedure MyDBGrid1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure MyDBGrid1DragOver(Sender, Source: TObject;
X, Y: Integer; State: TDragState; var Accept: Boolean);
procedure MyDBGrid1DragDrop(Sender, Source: TObject;
X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

var
SGC : TGridCoord;

procedure TForm1.MyDBGrid1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
DG : TMyDBGrid;
begin
DG := Sender as TMyDBGrid;
SGC := DG.MouseCoord(X,Y);
if (SGC.X > 0) and (SGC.Y > 0) then
(Sender as TMyDBGrid).BeginDrag(False);
end;

procedure TForm1.MyDBGrid1DragOver(Sender, Source: TObject;
X, Y: Integer; State: TDragState; var Accept: Boolean);
var
GC : TGridCoord;
begin
GC := (Sender as TMyDBGrid).MouseCoord(X,Y);
Accept := Source is TMyDBGrid and (GC.X > 0) and (GC.Y > 0);
end;

procedure TForm1.MyDBGrid1DragDrop(Sender, Source: TObject;
X, Y: Integer);
var
DG : TMyDBGrid;
GC : TGridCoord;
CurRow : Integer;
begin
DG := Sender as TMyDBGrid;
GC := DG.MouseCoord(X,Y);
with DG.DataSource.DataSet do begin
with (Source as TMyDBGrid).DataSource.DataSet do
Caption := 'You dragged "'+Fields[SGC.X-1].AsString+'"';
DisableControls;
CurRow := DG.Row;
MoveBy(GC.Y-CurRow);
Caption := Caption+' to "'+Fields[GC.X-1].AsString+'"';
MoveBy(CurRow-GC.Y);
EnableControls;
end;
end;

end.

----- Dfm 파일 -----
object Form1: TForm1
Left = 200
Top = 108
Width = 544
Height = 437
Caption = 'Form1'
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
PixelsPerInch = 96
TextHeight = 13
object MyDBGrid1: TMyDBGrid
Left = 8
Top = 8
Width = 521
Height = 193
DataSource = DataSource1
Row = 1
TabOrder = 0
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
OnDragDrop = MyDBGrid1DragDrop
OnDragOver = MyDBGrid1DragOver
OnMouseDown = MyDBGrid1MouseDown
end
object MyDBGrid2: TMyDBGrid
Left = 7
Top = 208
Width = 521
Height = 193
DataSource = DataSource2
Row = 1
TabOrder = 1
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
OnDragDrop = MyDBGrid1DragDrop
OnDragOver = MyDBGrid1DragOver
OnMouseDown = MyDBGrid1MouseDown
end
object Table1: TTable
Active = True
DatabaseName = 'DBDEMOS'
TableName = 'ORDERS'
Left = 104
Top = 48
end
object DataSource1: TDataSource
DataSet = Table1
Left = 136
Top = 48
end
object Table2: TTable
Active = True
DatabaseName = 'DBDEMOS'
TableName = 'CUSTOMER'
Left = 104
Top = 240
end
object DataSource2: TDataSource
DataSet = Table2
Left = 136
Top = 240
end
end

dbgrid 에서 cell 모양의 색깔 바꾸기

Procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;
Field: TField; State: TGridDrawState);
begin
If gdFocused in State then
with (Sender as TDBGrid).Canvas do

begin
Brush.Color := clRed;
FillRect(Rect);
TextOut(Rect.Left, Rect.Top, Field.AsString);
end;
end;

화면에 보여기는 DBGrid내용을 처리하기

var i: integer;
begin
with TDrawGrid(DBGrid1), DBGrid1.DataSource.DataSet do
begin
while TopRow < Row do Prior;
for i:= TopRow to RowCount - 1 do
begin
Memo1.Lines.Add(FieldByName('CD_DTL').AsString);
if i < RowCount - 1 then
Next;
end;
end;
end;

찾지말고 통 하자!

JPEG, String 사용하는 방법

.RC 파일내용

MYJPEG JPEG C:\DownLoad\MY.JPG

StringTable
begin
1, "DPSC"
2, "Tips"
3, "Source Code"
4, "Interviews, reviews, and articles"
end

ARJ EXEFILE C:\UTILS\ARJ.EXE

WAVEFILE WAVE c:\WaveSound.wav
MAINICON ICON "MainIcon.ico"

uses Jpeg;

procedure LoadJPEGFromRes(TheJPEG : string; ThePicture : TPicture);
var
ResHandle : THandle;
MemHandle : THandle;
MemStream : TMemoryStream;
ResPtr : PByte;
ResSize : Longint;
JPEGImage : TJPEGImage;
begin
ResHandle := FindResource(hInstance, PChar(TheJPEG), 'JPEG');
MemHandle := LoadResource(hInstance, ResHandle);
ResPtr := LockResource(MemHandle);

// create instance of objects.
MemStream := TMemoryStream.Create;
JPEGImage := TJPEGImage.Create;

ResSize := SizeOfResource(hInstance, ResHandle);
MemStream.SetSize(ResSize);
MemStream.Write(ResPtr^, ResSize);
FreeResource(MemHandle);
MemStream.Seek(0, 0);
JPEGImage.LoadFromStream(MemStream);
ThePicture.Assign(JPEGImage);

// remove from memory.
JPEGImage.Free;
MemStream.Free;
end;


사용 예) LoadJPEGFromRes('MYJPEG', Image1.Picture);

//String사용 예

procedure TForm1.Button1Click(Sender: TObject);
var Buffer : Array[0..255] Of Char;
begin
LoadString(hInstance, 1, @Buffer, 255);
Label1.Caption := StrPas(Buffer);
LoadString(hInstance, 2, @Buffer, 255);
Label2.Caption := StrPas(Buffer);
end;


//파일저장 함수

procedure ExtractRes(ResType, ResName, ResNewName : String);
var
Res : TResourceStream;
begin
Res := TResourceStream.Create(Hinstance, Resname, Pchar(ResType));
Res.SavetoFile(ResNewName);
Res.Free;
end;

사용 예) ExtractRes('EXEFILE', 'ARJ', 'ARJ-1.EXE');

//WAVE예제

var
Soo: TResourceStream;
begin
Soo := TResourceStream.Create(hInstance, 'WAVEFILE', PChar('Wave'));
sndPlaySound(Soo.Memory, SND_MEMORY or SND_ASYNC);
Soo.Free;
end;

//아이콘변경

SetClassLong( Dialog, GCL_HICON, LoadIcon( hInstance, 'MAINICON'));

찾지말고 통 하자!

bde 를이용해 동적으로 엘리어스 만들기

uses BDE;

procedure AddBDEAlias(sAliasName, sAliasPath, sDBDriver : string );
var h : hDBISes;
begin;
DBIInit( nil );
DBIStartSession( 'dummy', h, '' );
DBIAddAlias( nil, PChar( sAliasName ), PChar( sDBDriver ), PChar( 'PATH:' + sAliasPath ), True );

DBICloseSession( h );
DBIExit;
end;

사용 예) AddBDEAlias('TestDB','C:\Temp', 'DBASE' );

BDE 버전정보

uses BDE;


function BDEVersion: string;
var BDEVer: SYSVersion;
Day,Month,Hour,Min,MilliSec: Word;
Year: Smallint;
begin
DbiGetSysVersion(BDEVer);
with BDEVer do
begin
DbiDateDecode(dateVer, Month, Day, Year);
DbiTimeDecode(TimeVer, Hour, Min, MilliSec);
Result := format('Database Engine version %d.%.3d of %.2d/%.2d/%d, %.2dh:%.2dm:%.2ds',
[Hi(iVersion),Lo(iVersion),Month,Day,Year,Hour,Min,MilliSec div 1000]);
end;
end;

BDE가 설치되어있는지 알아내기

1. 레지스트리를 이용한 방법

RootKey := HKEY_LOCAL_MACHINE;
OpenKey('SOFTWARE\Borland\Database Engine', False);
try
s := ReadString('CONFIGFILE01');
//BDE installed
finally
CloseKey;
end;

2. BDE를 초기화 해보는 방법

IsBDEExist := (dbiInit(nil) = 0)

두번째 방법이 더 신뢰성이 있습니다. BDE프로그램파일만 지우고 레지스트리정보는 정리하지 않은 경우가
있기때문이죠.

BDE Error list 얻기

procedure TForm1.Button1Click(Sender: TObject);
var Category: byte;
Code: byte;
ResultCode: word;
ErrorString: array[0..DBIMAXMSGLEN + 1] of char;
OutString: string;
begin
DbiInit(nil);

Memo1.Lines.BeginUpdate;
for Category := ERRCAT_NONE to ERRCAT_RC do
for Code := 0 to 255 do
begin
ResultCode := (Category shl 8) + Code;
DbiGetErrorString(ResultCode, ErrorString);
if StrLen(ErrorString) > 0 then
begin
OutString := Format('%6d %0.4x %s', [ResultCode, ResultCode, ErrorString]);
Memo1.Lines.Add(OutString);
end;
end;
Memo1.Lines.EndUpdate;

DbiExit;
end;

bde의 제한

Table and Index Files
48 Clients in system
32 Sessions per client (3.5 and earlier, 16 Bit, 32 Bit)
256 Session per client (4.0, 32 Bit)
32 Open databases per session (3.5 and earlier, 16 Bit, 32 Bit)
2048 Open databases per session (4.0, 32 Bit)
32 Loaded drivers
64 Sessions in system (3.5 and earlier, 16 Bit, 32 Bit)
12288 Sessions in system (4.0, 32 Bit)
4000 Cursors per session
16 Entries in error stack
8 Table types per driver
16 Field types per driver
8 Index types per driver
48K Size of configuration (IDAPI.CFG) file
64K Size of SQL statement (RequestLive=False)
4K Size of SQL statement (RequestLive=True)
16K Record buffer size (SQL or ODBC)

찾지말고 통 하자!

이미지를 db에 저장하기

procedure TForm1.Button1Click(Sender: TObject);
begin
Query1.Close;
Query1.SQL.Clear;
Query1.SQL.Add('INSERT INTO test_pic ');
Query1.SQL.Add('(pic_NO,pic_IMAGE) ');
Query1.SQL.Add('VALUES (:pic_NO, :pic_IMAGE)');
Query1.ParamByName('pic_no').AsString := Edit1.Text;
Query1.ParamByName('pic_IMAGE').LoadFromFile('c:\aaaa\4444.jpg',FTBLOB);
Query1.Prepare;
Query1.ExecSQL;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Query2.open;
// table1.open;
end;

procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);
var
aJpeg : TJpegImage;
Buffer: PChar;
MemSize: Integer;
BStream : TStream;
begin
Image1.Picture := nil;
BStream := Query2.CreateBlobStream(Query2.FieldByName('pic_IMAGE'),bmRead);
// BStream := table1.CreateBlobStream(table1.FieldByName('pic_IMAGE'),bmRead);
MemSize := BStream.Size;
Inc(MemSize);
Buffer := AllocMem(MemSize);
try
BStream.Read(Buffer^, MemSize);
BStream.Position := 0;
aJpeg := TJPEGImage.Create;
try
aJpeg.LoadFromStream(BStream);
Image1.Picture.Assign(aJpeg);
finally
aJpeg.Free;
end;
finally
FreeMem(Buffer, MemSize);
end;

end;

blob 사용법

// 다음은 TBlobStream을 사용한 BLOB field와의 연동을 Rich Edit를 예를들어
// 작성했습니다.
if DataSource1.DataSet.FieldByName(field) is TMemoField then
begin
aBlobStream := TBlobStream.Create(
TMemoField(DataSource1.DataSet.FieldByName(field)),
bmRead);
RichEdit1.Lines.LoadFromStream(aBlobStream);
// DataSource1은 TTable과 연결해놓으세요.
procedure TForm1.LoadFromBLOB(field: String); {field는 TTable의 BLOB 필드명}
var
aBlobStream: TBlobStream;
begin
if ((DataSource1 <> nil) and (field <> '')) then
begin
{그래픽을 다루는 프로그램이면 TMemoField -> TGraphicField로}
if DataSource1.DataSet.FieldByName(field) is TMemoField then
begin
aBlobStream := TBlobStream.Create(
TMemoField(DataSource1.DataSet.FieldByName(field)),
bmRead);
RichEdit1.Lines.LoadFromStream(aBlobStream);
aBlobStream.Free;
end
else
begin
RichEdit1.Text := DataSource1.DataSet.FieldByName(field).AsString;
end;
end;
end;

// 물론 아래의 SaveToBLOB를 호출하기전에 TTable을 edit 나
// insert상태로 만들어 놓고 사용해야죠, 그리고 호출후 post도...
procedure TForm1.SaveToBLOB(field: String); {field는 TTable의 BLOB 필드명};
var
aBlobStream: TBlobStream;
begin
if ((DataSource1 <> nil) and (field <> '')) then
begin
if DataSource1.DataSet.FieldByName(field) is TMemoField then
begin
aBlobStream := TBlobStream.Create(
TMemoField(DataSource1.DataSet.FieldByName(field)),
bmWrite);
RichEdit1.Lines.SaveToStream( aBlobStream );
aBlobStream.Free;
end
else
begin
DataSource1.DataSet.FieldByName(field).AsString := RichEdit1.Text;
end;
end;
end;

dataset의 현재 레코드 복사하여 붙여넣기

procedure AppendCurrent(Dataset:Tdataset);
var
aField: Variant;
i: Integer;
begin
// 주어진 DataSet(TTable, TQuery...)의 필드 갯수만큼의 배열요소 갯수로
// Variant 배열을 만든다
aField := VarArrayCreate([0, DataSet.Fieldcount-1], VarVariant);

// Variant 배열에 모든 필드의 값을 저장한다
for i := 0 to (DataSet.Fieldcount-1) do
aField[i] := DataSet.fields[i].Value;

// DataSet의 상태를 insert로 만든다
DataSet.Append ;

// Variant 배열에 저장된 필드의 값을 신규 레코드의 해당 필드에 할당한다
for i := 0 to (DataSet.Fieldcount-1) do
DataSet.fields[i].Value := aField[i];
end;

blob 필드에서 다른 table의 blob 필드로 복사를 하려면...

procedure TForm1.Button1Click(Sender: TObject);
var
BS1, BS2: TBlobStream;
begin
BS1 := TBlobStream.Create(Table1Notes,bmRead);
try
Table2.Edit;
BS2 := TBlobStream.Create(Table2MyBlob,bmReadWrite);
try
BS2.CopyFrom(BS1,BS1.Size);
finally
BS2.Free;
end;
finally
BS1.Free;
end;
Table2.Post;
end;

blob필드의 size 구하는 함수

function GetBlobSize(Field: TBlobField): Longint;
var
bi: TBlobStream;
begin
bi := TBlobStream.Create(Field, bmRead);
try
Result := bi.Seek(0,2);
finally
bi.Free;
end;
end;

sqlserver에서 프로시져호출

with Query1 do begin { 추가 }
Close;
Sql.Clear;
Sql.Add('declare @bal_sno numeric(07,0) ');
Sql.Add(' ,@io_no numeric(03,0) ');
Sql.Add(' ,@bal_no varchar(20) ');
Sql.Add('select @bal_sno = :bal_sno ');
Sql.Add('select @io_no = :io_no ');
Sql.Add('select @bal_no = :bal_no ');
Sql.Add('exec SP_JJ_BALJU_I @bal_sno output ');
Sql.Add(' ,:sa_sno ,:b_sno ,:io_store ');
Sql.Add(' ,@io_no output ,:io_seq ');
Sql.Add(' ,:io_date ,:c_sno ,:js_sno ,:jb_sno ');
Sql.Add(' ,:j_sno ,:io_qty ,:io_price ,:io_amt ');
Sql.Add(' ,:m_name ,:w_whan ,:io_amt_w ,:d_date ');
Sql.Add(' ,@bal_no output ,:bal_gubun ,:chk_inv ');
Sql.Add(' ,:needj_sno ,:can_qty ,:inv_qty ,:ga_qty ');
Sql.Add(' ,:bad_qty ');
Sql.Add('select @io_no as IO_NO ');
ParamByName('bal_sno' ).AsInteger := MEditBAL_NO.Tag;
ParamByName('sa_sno' ).AsInteger := MeditSA_NAME.Tag;
ParamByName('b_sno' ).AsInteger := MeditB_NAME.Tag;
ParamByName('io_store' ).AsInteger := MeditIO_STORE.Tag;
ParamByName('io_no' ).AsFloat := MeditIO_NO.ValueF;
ParamByName('io_seq' ).AsInteger := 0;
ParamByName('io_date' ).AsDate := MeditIO_DATE.ValueD;
ParamByName('c_sno' ).AsInteger := MeditC_NAME.Tag;
ParamByName('js_sno' ).AsInteger := MeditJS_NAME.Tag;
ParamByName('jb_sno' ).AsInteger := MeditJB_NAME.Tag;
ParamByName('j_sno' ).AsInteger := MeditJ_NAME.Tag;
ParamByName('io_qty' ).AsFloat := MeditIO_QTY.ValueF;
ParamByName('io_price' ).AsFloat := MeditIO_PRICE.ValueF;
ParamByName('io_amt' ).AsFloat := MeditIO_AMT.ValueF;
ParamByName('m_name' ).AsString := MeditM_NAME.Text;
ParamByName('w_whan' ).AsFloat := MeditW_WHAN.ValueF;
ParamByName('io_amt_w' ).AsFloat := MeditIO_AMT_W.ValueF;
if MEditD_DATE.Text = ' - - ' then
ParamByName('d_date' ).AsString := ''
else
ParamByName('d_date' ).AsDate := MEditD_DATE.ValueD;
ParamByName('bal_no' ).AsString := '';//MeditBAL_NO.Text;
ParamByName('bal_gubun').AsInteger := 1; //발주구분:0=일괄,1=개별
ParamByName('chk_inv' ).AsInteger := RadioGroupCHK_INV.ItemIndex;
ParamByName('needj_sno').AsInteger := 0; //소요량계산키
ParamByName('can_qty' ).AsFloat := 0; //취소수량
ParamByName('inv_qty' ).AsFloat := 0; //Invoice수량
ParamByName('ga_qty' ).AsFloat := 0; //가입수량
ParamByName('bad_qty' ).AsFloat := 0; //불량수량
Open;
MEditIO_NO.Tag := FieldByName('IO_NO').AsInteger;
end;

sqlserver에서 삭제(delete) sql문사용

with Query1 do begin
Close;
Sql.Clear;
Sql.Add('declare @error_cnt numeric ');
Sql.Add('select @error_cnt = 0 ');
Sql.Add('begin tran ');
Sql.Add(' delete from JJ_BALJU where BAL_SNO = :bal_sno');
Sql.Add(' select @error_cnt = @error_cnt + @@error ');
Sql.Add('if @error_cnt = 0 COMMIT else ROLLBACK TRAN ');
Params[0].AsInteger := QueryIO.FieldByName('BAL_SNO').AsInteger;
ExecSql;
end;

bitmap을database field로 loading하는 법

TImage 컴포넌트를 이용하거나 그래픽 툴을 이용하거나
프로그램 자체내에 클립보드에 Bitmap 파일을 Copy하는
기능을 가지고 TClipboard에 Bitmap을 Paste하는 것이
바로 이 방법입니다.

TTable과 TDataSource, TDBGrid, 그리고 TDBImage정도면
쉽게 구현을 할 수 있습니다.

TDBImage에는 PasteFromClipboard 메소드가 있습니다..
이를 이용하여 DB에 Bitmap 이미지를 저장하게 됩니다.

여기에서 DB에 이미지를 저장하기전, Clipboard에서
데이타의 포맷이 어떤 것인지 체크하는 것이 작성한
프로그램에 버그를 없애는데 한 몫을 합니다.

아래 예제는 Clipboard의 데이타 포맷을 체크하고 BITMAP일
경우 TDBImage에 이미지를 Paste하는 예입니다.

그리고, 또 한가지 TClipboard 개체를 사용하기 위하여
Clipbrd 유닛을 사용하여야 합니다.
Uses섹션에 추가하는 것을 잊지 맙시다.

Procedure TFrom1.Button1Click(Sender:TObject);
var
C:TClipboard;
Begin
C := TClipboard.Create; // creating TClipboard
Try
If Clipboard.HasFormat(CF_BITMAP) Then // check data format at clipboard
DBImage1.PasteFromClipboard // paste image to DBImage
Else // fail
ShowMessage('Clipboard does not contain a bitmap');
Finally
C.Free; // remove at the memory
End;
End;

찾지말고 통 하자!

화면상에 키보드 Down
var b: Byte;
begin
//문자를 숫자로 변환
b:= ord('A');

//키보드 누름
Keybd_Event( B, MapVirtualkey( B, 0 ), 0, 0 );

end;

THotKey사용 및 전역HotKey로 등록

//THotKey.HotKey같을 받아서 Key값과 Shift값으로 분리한다.

procedure ShortCutDiv(var Key, Shift: Integer);
begin
Shift:= 0;
if (Key shr 15) = 1 then
begin
Key:= Key xor (1 shl 15);
Shift:= MOD_ALT;
end;
if (Key shr 14) = 1 then
begin
Key:= Key xor (1 shl 14);
Shift:= Shift or MOD_CONTROL;
end;
if (Key shr 13) = 1 then
begin
Key:= Key xor (1 shl 13);
Shift:= Shift or MOD_SHIFT;
end;
end;

사용)

//선언부

//HotKey이벤트 발생을 처리

procedure WMHotKey(var Message: TWMHotKey); message WM_HotKey;

var iHotKey; //전역변수로 선언

procedure TFrmMain.WMHotKey(var Message: TWMHotKey);
begin
if Message.HotKey = iHotKey then
begin
//할일
end;
end;

//HotKey값을 받아서 RegisterHotKey로 등록한다.

procedure TFrmMain.Button1Click(Sender: TObject);
var k, sc: Integer;
s: string;
begin
k:= HotKey1.HotKey;
ShortCutDiv(k, sc); //Key값과 Shift값을 분리한다.
UnRegisterHotKey(Self.Handle, iHotKey);
iHotKey:= GlobalAddAtom('xxx');
if not RegisterHotKey(Self.Handle,iHotKey, sc, k) then
ShowMessage('HotKey등록 실패');
end;

KeyPress 키값

sTmp := IntToStr(Ord(Key));

KeyDown 키값
var
tempstr: string; {used to spell out keys typed}
begin

{be sure to set Form.KeyPreview to True}

Edit4.Text := '';
if (Shift = ([ssShift])) then Edit4.Text := Edit4.Text + 'Shift';
if (Shift = ([ssShift, ssAlt])) then Edit4.Text := Edit4.Text + 'Shift+Alt';
if (Shift = ([ssShift, ssCtrl])) then Edit4.Text := Edit4.Text + 'Shift+Ctrl';
if (Shift = ([ssShift, ssAlt, ssCtrl])) then Edit4.Text := Edit4.Text + 'Shift+Ctrl+Alt';
if (Shift = ([ssAlt])) then Edit4.Text := Edit4.Text + 'Alt';
if (Shift = ([ssAlt, ssCtrl])) then Edit4.Text := Edit4.Text + 'Ctrl+Alt';
if (Shift = ([ssCtrl])) then Edit4.Text := Edit4.Text + 'Ctrl';

tempstr := '';

case Key of
VK_CANCEL: tempstr := 'CANCEL';
VK_BACK: tempstr := 'BACKSPACE';
VK_TAB: tempstr := 'TAB';
VK_CLEAR: tempstr := 'CLEAR';
VK_RETURN: tempstr := 'ENTER';
VK_PAUSE: tempstr := 'PAUSE';
VK_CAPITAL: tempstr := 'CAPS LOCK';
VK_ESCAPE: tempstr := 'ESC';
VK_SPACE: tempstr := 'SPACEBAR';
VK_PRIOR: tempstr := 'PAGE UP';
VK_NEXT: tempstr := 'PAGE DOWN';
VK_END: tempstr := 'END';
VK_HOME: tempstr := 'HOME';
VK_LEFT: tempstr := 'LEFT ARROW';
VK_UP: tempstr := 'UP ARROW';
VK_RIGHT: tempstr := 'RIGHT ARROW';
VK_DOWN: tempstr := 'DOWN ARROW';
VK_SELECT: tempstr := 'SELECT';
VK_EXECUTE: tempstr := 'EXECUTE';
VK_SNAPSHOT: tempstr := 'PRINT SCREEN';
VK_INSERT: tempstr := 'INS';
VK_DELETE: tempstr := 'DEL';
VK_HELP: tempstr := 'HELP';

{VK_1..VK_0 and VK_A..VK_Z are not defined so you have to use the Ord()
function instead which yields the equivilent VK code}

Ord('0'): tempstr := '0';
Ord('1'): tempstr := '1';
Ord('2'): tempstr := '2';
Ord('3'): tempstr := '3';
Ord('4'): tempstr := '4';
Ord('5'): tempstr := '5';
Ord('6'): tempstr := '6';
Ord('7'): tempstr := '7';
Ord('8'): tempstr := '8';
Ord('9'): tempstr := '9';
Ord('A'): tempstr := 'A';
Ord('B'): tempstr := 'B';
Ord('C'): tempstr := 'C';
Ord('D'): tempstr := 'D';
Ord('E'): tempstr := 'E';
Ord('F'): tempstr := 'F';
Ord('G'): tempstr := 'G';
Ord('H'): tempstr := 'H';
Ord('I'): tempstr := 'I';
Ord('J'): tempstr := 'J';
Ord('K'): tempstr := 'K';
Ord('L'): tempstr := 'L';
Ord('M'): tempstr := 'M';
Ord('N'): tempstr := 'N';
Ord('O'): tempstr := 'O';
Ord('P'): tempstr := 'P';
Ord('Q'): tempstr := 'Q';
Ord('R'): tempstr := 'R';
Ord('S'): tempstr := 'S';
Ord('T'): tempstr := 'T';
Ord('U'): tempstr := 'U';
Ord('V'): tempstr := 'V';
Ord('W'): tempstr := 'W';
Ord('X'): tempstr := 'X';
Ord('Y'): tempstr := 'Y';
Ord('Z'): tempstr := 'Z';

VK_NUMPAD0: tempstr := 'Numeric keypad 0';
VK_NUMPAD1: tempstr := 'Numeric keypad 1';
VK_NUMPAD2: tempstr := 'Numeric keypad 2';
VK_NUMPAD3: tempstr := 'Numeric keypad 3';
VK_NUMPAD4: tempstr := 'Numeric keypad 4';
VK_NUMPAD5: tempstr := 'Numeric keypad 5';
VK_NUMPAD6: tempstr := 'Numeric keypad 6';
VK_NUMPAD7: tempstr := 'Numeric keypad 7';
VK_NUMPAD8: tempstr := 'Numeric keypad 8';
VK_NUMPAD9: tempstr := 'Numeric keypad 9';
VK_MULTIPLY: tempstr := 'Multiply';
VK_ADD: tempstr := 'Add';
VK_SEPARATOR: tempstr := 'Separator';
VK_SUBTRACT: tempstr := 'Subtract';
VK_DECIMAL: tempstr := 'Decimal';
VK_DIVIDE: tempstr := 'Divide';
VK_F1: tempstr := 'F1';
VK_F2: tempstr := 'F2';
VK_F3: tempstr := 'F3';
VK_F4: tempstr := 'F4';
VK_F5: tempstr := 'F5';
VK_F6: tempstr := 'F6';
VK_F7: tempstr := 'F7';
VK_F8: tempstr := 'F8';
VK_F9: tempstr := 'F9';
VK_F10: tempstr := 'F10';
VK_F11: tempstr := 'F11';
VK_F12: tempstr := 'F12';
VK_F13: tempstr := 'F13';
VK_F14: tempstr := 'F14';
VK_F15: tempstr := 'F15';
VK_F16: tempstr := 'F16';
VK_F17: tempstr := 'F17';
VK_F18: tempstr := 'F18';
VK_F19: tempstr := 'F19';
VK_F20: tempstr := 'F20';
VK_F21: tempstr := 'F21';
VK_F22: tempstr := 'F22';
VK_F23: tempstr := 'F23';
VK_F24: tempstr := 'F24';
VK_NUMLOCK: tempstr := 'NUM LOCK';
VK_SCROLL: tempstr := 'SCROLL LOCK';
end;
if Edit4.Text = '' then Edit4.Text := tempstr
else if tempstr <> '' then Edit4.Text := Edit4.Text + '+' + tempstr;
Key := 0; {set key to 0 to send no key stroke}

Ctrl -Alt-Del Key Enable/Disable

var
iDummy: Integer;
begin
SystemParametersInfo(97, Word(True), @iDummy, 0); //Disable
SystemParametersInfo(97, Word(False), @iDummy, 0); //Enable
end;

출처 : Tong - BlueSky_07님의 DELPHI통

댓글 1개:

Blogger :

Are you trying to make cash from your visitors by using popup advertisments?
In case you are, did you try using EroAdvertising?