Klinik Mr. Delphi
Telah dimuat di majalah Mikrodata.
Daftar Isi
Keamanan Aplikasi
Membuat Map Network Drive
Mengetahui UNC Suatu File
Mewarnai DBGrid
Menduplikatkan Form Saat Runtime
Apakah Hash itu ??
Membuat GUID Saat Runtime
Mengetahui Uptime Windows
Baris Kosong dalam TMemo
Scroll ke Akhir TMemo/TRichEdit
Memaksa TDateTimePicker untuk Drop-down Otomatis
Version Control dalam Delphi
Jawab:
Ok, yang penting jangan bingung dulu, mari kita teliti lebih seksama lagi. Dalam kasus
Anda berarti ada dua macam pembatasan, secara aplikasi dan secara masing-masing user.
Pembatasan bisa diberikan dengan nama komputer, alamat IP, MAC Address, dll. Dalam contoh
berikut, kita gunakan alamat IP dan nama komputer, tergantung yang telah didefinisikan,
bisa salah satu, bisa kedua-duanya. Namun perlu diingat bahwa workstation harus
dikonfigurasikan agar user tidak berhak untuk merubah alamat IP maupun nama komputer, juga
diasumsikan tidak menggunakan DHCP.
Dalam aplikasi ini, kita membutuhkan tiga tabel, yaitu:
Inti logika dari pemrograman ini adalah:
Lalu pemrogramannya adalah sebagai berikut:
procedure TfrmAppSec.btnLoginClick(Sender: TObject);
var
cUserID, cUserPass, cIP, cPcName: String;
begin
cUserID := Trim( edtUserID.Text );
cUserPass := Trim( edtPassword.Text );
if chkUser( cUserID, cUserPass ) then begin
cIP := getComputerIP();
cPcName := getComputerName();
if chkAppSec( cIP, cPcName ) and chkAppUser( cUserID, cIP, cPcName ) then begin
ShowMessage( 'Login Ok!' );
// Lanjutkan proses
end else
ShowMessage( 'User tidak diperkenankan login di workstation ini!' );
end else
ShowMessage( 'Kombinasi UserID dan Password salah!' );
end;
function TfrmAppSec.ChkUser( cUserID, cPassword: String ): Boolean;
begin
Result := tblUser.Locate( 'UserID;UserPass', VarArrayOf( [ cUserID, cPassword ] ), [] );
end;
function TfrmAppSec.chkAppSec( cIP, cPcName: String ): Boolean;
begin
Result := ( tblAppSec.Locate( 'IP;PcName', VarArrayOf( [ cIP, cPcName ] ), [] ) ) or
( tblAppSec.Locate( 'IP', cIP, [] ) ) or
( tblAppSec.Locate( 'PcName', cPcName, [] ) );
end;
function TfrmAppSec.chkAppUser( cUserID, cIP, cPcName: String ): Boolean;
begin
Result := ( tblUserSec.Locate( 'UserID;IP;PcName', VarArrayOf( [ cUserID, cIP, cPcName ] ), [] ) ) or
( tblUserSec.Locate( 'UserID;IP', VarArrayOf( [ cUserID, cIP ] ), [] ) ) or
( tblUserSec.Locate( 'UserID;PcName', VarArrayOf( [ cUserID, cPcName ] ), [] ) );
end;
function TfrmAppSec.GetComputerName: String;
var
wsaData: TWSAData;
cHostName: String;
begin
WSAStartup( 257, wsaData );
cHostName := GetHostByName( NIL )^.h_name;
WSACleanup;
Result := cHostName;
end;
function TfrmAppSec.GetComputerIP: String;
var
wsaData: TWSAData;
cIP: String;
begin
WSAStartup( 257, wsaData );
cIP := iNet_ntoa( PInAddr( GetHostByName( NIL )^.h_addr_list^ )^ );
WSACleanup;
Result := cIP;
end;
end.
Jawab:
Kita dapat menggunakan fungsi WNetAddConnection2 untuk membuat koneksi ke shared folder
dan fungsi WNetCancelConnection2 untuk memutuskan koneksi.
Berikut ini ada contoh yang telah disederhanakan, Anda cukup membuat suatu form dan 2 button seperti berikut:
procedure TfrmNetworkMap.btnConnectClick(Sender: TObject);
begin
if NetUse( Trim( edtDrive.Text ), Trim( edtUNC.Text ), Trim( edtPassword.Text ) ) then
modeConnect( False )
else
ShowMessage( 'Error: Tidak bisa melakukan map network drive !' );
end;
procedure TfrmNetworkMap.btnDisconnectClick(Sender: TObject);
begin
if NetDel( Trim( edtDrive.Text ) ) then
modeConnect( True )
else
ShowMessage( 'Error: Tidak bisa menghapus map network drive !' );
end;
function TfrmNetworkMap.NetUse( cDrive, cUNC, cPassword: String): Boolean;
var
nr: TNetResource;
begin
if cDrive = '' then
nr.lpLocalName := nil
else
nr.lpLocalName := PChar( cDrive );
nr.dwType := RESOURCETYPE_DISK;
nr.lpRemoteName := PChar( cUNC );
nr.lpProvider := nil;
Result := WNetAddConnection2( nr, PChar( cPassword ), nil, 0 ) = NO_ERROR;
end;
function TfrmNetworkMap.NetDel( cDrive: String ): Boolean;
begin
Result := WNetCancelConnection2( PChar( cDrive ), 0, False ) = NO_ERROR;
end;
end.
Jawab:
Anda dapat menggunakan fungsi ExpandUNCFileName, yang akan menghasilkan pengalamatan UNC
yang lengkap, misalnya \\192.168.0.1\IT\User\Hian\mrdelphi.doc, silakan lihat pada contoh
berikut:
procedure TfrmUncPath.btnFindOutClick(Sender: TObject); begin edtUnc.Text := ExpandUNCFileName( edtFileName.Text ); end;
Jawab:
Anda dapat menggunakan event DrawColumnCell, dimana Anda definisikan warna maupun font
dengan mengubah property Canvas dari DBGrid seperti pada contoh berikut ini:
procedure TfrmColorDbGrid.grdColorDrawColumnCell(Sender: TObject;
const Rect: TRect; DataCol: Integer; Column: TColumn;
State: TGridDrawState);
var
nArea: LongInt;
begin
// Check the field value and assign a color
nArea := tblColor.FieldByName( 'AREA' ).AsInteger;
if nArea < 1000000 then
grdColor.Canvas.Brush.Color := clBlue
else if nArea < 2000000 then
grdColor.Canvas.Brush.Color := clAqua
else if nArea < 3000000 then
grdColor.Canvas.Brush.Color := clRed
else begin
grdColor.Canvas.Brush.Color := clTeal;
grdColor.Canvas.Font.Style := [ fsBold ];
end;
grdColor.DefaultDrawColumnCell( Rect, DataCol, Column, State );
end;
Jawab:
Bisa, kita lakukan dengan memanfaatkan fasilitas streaming dalam Delphi. Silakan
lihat code seperti ini:
procedure TfrmMain.btnDupeFormClick(Sender: TObject);
var
ms: TMemoryStream;
frmDuplicate: TfrmMain;
begin
ms := TMemoryStream.Create;
try
ms.WriteComponent( frmMain );
frmDuplicate := TfrmMain.CreateNew( Application );
ms.Position := 0;
ms.ReadComponent( frmDuplicate );
// Lokasi dirubah agar terlihat di layar
frmDuplicate.Top := 0;
frmDuplicate.Left := 0;
frmDuplicate.Show;
finally
ms.Free;
end;
end;
Jawab:
Hash merupakan penghitungan suatu string menjadi suatu nilai yang lebih pendek yang bisa
mewakili string tersebut. Hash banyak dipakai pada algoritma enkripsi maupun index.
Hash sudah diterapkan di Delphi dan dapat kita baca pada source code VCL secara langsung di file dbtables.pas, seperti yang saya cuplik berikut ini:
function GetHashCode(Str: PChar): Integer;
var
Off, Len, Skip, I: Integer;
begin
Result := 0;
Off := 1;
Len := StrLen(Str);
if Len < 16 then
for I := (Len - 1) downto 0 do
begin
Result := (Result * 37) + Ord(Str[Off]);
Inc(Off);
end
else
begin
{ Only sample some characters }
Skip := Len div 8;
I := Len - 1;
while I >= 0 do
begin
Result := (Result * 39) + Ord(Str[Off]);
Dec(I, Skip);
Inc(Off, Skip);
end;
end;
end;
Bila Anda masih penasaran dan ingin mencari komponen Hash siap pakai, silakan mencoba salah satu contoh yaitu HashLib! v1.02 oleh Alex Demchenko (alex@ritlabs.com) yang bisa di-download langsung di http://www.torry.net/vcl/security/crypting/adhashlib.zip atau bisa ditemui pada CD Mikrodata edisi ini.
Jawab:
Ya, dalam hal ini, Anda dapat menggunakan GUID. GUID adalah kependekan dari Globally
Unique Identifier, yang berarti suatu identitas yang dijamin unik secara global. Adapun
cara untuk membuat GUID saat runtime adalah:
// Tambahkan ComObj, ActiveX pada uses
function TfrmCreateGUID.CreateGUID: String;
var
ID: TGUID;
begin
Result := '';
if CoCreateGuid( ID ) = S_OK then
Result := GUIDToString( ID );
end;
procedure TfrmCreateGUID.btnCreateGUIDClick(Sender: TObject);
begin
edtGUID.Text := CreateGUID;
end;
Jawab:
Anda bisa menggunakan fungsi GetTickCount, namun ingat, GetTickCount akan menghasilkan
suatu angka dalam satuan milidetik yang menyatakan berapa tick telah berjalan sejak
Windows dinyalakan, sehingga Anda harus membaginya dengan 1000 untuk mendapatkan hasil
dalam satuan detik. Lihat contoh pemrograman berikut ini:
function TfrmMain.Uptime: String;
const
nTicksPerDay: Integer = 1000 * 60 * 60 * 24;
nTicksPerHour: Integer = 1000 * 60 * 60;
nTicksPerMinute: Integer = 1000 * 60;
nTicksPerSecond: Integer = 1000;
var
lwUptime: LongWord;
nDay, nHour, nMin, nSec: Integer;
begin
lwUptime := GetTickCount;
nDay := lwUptime div nTicksPerDay;
Dec( lwUptime, nDay * nTicksPerDay );
nHour := lwUptime div nTicksPerHour;
Dec( lwUptime, nHour * nTicksPerHour );
nMin := lwUptime div nTicksPerMinute;
Dec( lwUptime, nMin * nTicksPerMinute );
nSec := lwUptime div nTicksPerSecond;
Result := IntToStr( nDay ) + ' hari ' +
IntToStr( nHour ) + ' jam ' +
IntToStr( nMin ) + ' menit ' +
IntToStr( nSec ) + ' detik ';
end;
procedure TfrmMain.tmrWinUptimeTimer(Sender: TObject);
begin
edtWinUptime.Text := Uptime;
end;
Jawab:
Method Add akan menambahkan baris kosong. Agar tidak menambah baris kosong, dapat kita
siasati dengan seakan-akan melakukan proses penggantian teks dengan property SelStart dan
SelText.
Memo1.SelStart := Memo1.GetTextLen; Memo1.SelText := 'Memo';
Jawab:
'Paksaan' :-) ini dapat Anda lakukan dengan mengirimkan message WM_VSCROLL (Vertical
Scroll) dengan parameter SB_BOTTOM, lihat baris berikut:
PostMessage( Memo1.Handle, WM_VSCROLL, SB_BOTTOM, 0 );
Jawab:
Hmm, saya jadi heran, edisi Klinik Mr. Delphi ini koq banyak pemaksaan yah :-). Tentu
saja Anda dapat 'memaksa' TDateTimePicker ini untuk drop-down secara pemrograman, karena
TDateTimePicker akan menampilkan drop-down saat Anda menekan tombol F4, karenanya
solusinya menjadi cukup sederhana, kita emulasikan bahwa tombol F4 telah ditekan, gunakan
code berikut:
with DateTimePicker1 do begin Perform( WM_KEYDOWN, VK_F4, 0 ); Perform( WM_KEYUP, VK_F4, 0 ); end;
Terus terang hal ini sangat mengganggu, apakah ada solusi lain untuk mengatasi hal ini ?? Kalau bisa yang gratis yah :-)
Jawab:
Masalah ini sebenarnya dapat dengan mudah diselesaikan dengan utility Version Control.
Selain itu, utility ini juga dapat membantu kita untuk mengembalikan perubahan-perubahan
yang pernah kita lakukan walaupun secara bertingkat (berkali-kali). Ada banyak utility
semacam ini, namun untuk yang gratis dan cukup terintegrasi dengan Delphi, saya bisa
menyarankan FreeVCS dari Thomas Hensle, yang bisa Anda simak di http://www.freevcs.de
Ada dua macam FreeVCS, yaitu:
Dengan FreeVCS, kita mempunyai alur pengembangan seperti berikut:
FreeVCS Server mampu menyimpan project Anda dalam berbagai format, diantaranya DBISAM, Interbase, Oracle, MS SQL Server, FlashFiler, dan Informix.
Untuk lebih jelasnya, silakan Anda baca file Help di FreeVCS
Copyright © 2003, Hianoto Santoso