Custom MessageDlg
Artikel ini merupakan lanjutan dari Meng-Indonesia-kan MessageDlg yang pernah saya publikasikan beberapa bulan yang lalu (lebih tepatnya tahun yang lalu). Sebenarnya saya ingin mengangkat tema lain yang menurut saya lebih menarik, namun berhubung ada diskusi di forum Delphi Indonesia (Delphi-ID) mengenai membuat MessageDlg sesuai dengan keinginan secara dinamis, maka saya putuskan untuk menulisnya terlebih dahulu.
Ada anggapan bahwa artikel tersebut hanya menitik beratkan pada lokalisasi teks MessageDlg, sebenarnya lebih dari itu. Jika dicermati, saya memaparkan trik bagaimana mengubah judul dan tombol yang digunakan MessageDlg pada saat aplikasi berjalan (run-time). Kemudian trik tersebut saya kuatkan dengan demo agar lebih jelas dipahami. Oiya sekedar untuk diketahui trik tersebut berlaku global, untuk semua MessageDlg yang dipanggil oleh aplikasi yang menggunakan, tidak peduli berasal dari mana form atau unit pemanggilnya sampai aplikasi ditutup.
Ada anggapan bahwa trik tersebut bersifat sekali pakai saja, tidak dinamis. Nah inilah yang perlu saya luruskan. Tentu saja trik tersebut dapat dipanggil dan digunakan berkali – kali untuk menampilkan MessageDlg dengan judul dan teks tombol yang berbeda – beda pula.
Lalu bagaimanakah cara agar dapat menampilkan MessageDlg sesuai dengan konteks teks judul dan tombol yang kita inginkan?
Tentu saja cukup mudah!
Cukup panggil method ReplaceResourceString dengan parameter judul, tombol mana yang ingin diubah teks-nya.
Misalnya:
ReplaceResourceString(@SMsgDlgConfirm, 'Konfirmasi Penyimpanan'); ReplaceResourceString(@SMsgDlgYes, 'Simpan Perubahan'); ReplaceResourceString(@SMsgDlgNo, 'Jangan Simpan');
Ok, cukup, saya rasa Anda sudah mendapatkan inti-nya. Jika masih belum, coba simak kode sumber demo berikut, bagi yang belum paham, baca juga penjelasan yang saya tambahkan sebagai komentar:
{-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: CustomMessageDlgDemoUnit.pas, released on 2008-08-05
The Initial Developer of the Original Code is Bayu Prasetio
Portions created by Bayu Prasetio are Copyright (C) 2007, 2008 Bayu Prasetio.
All Rights Reserved.
-----------------------------------------------------------------------------}
{-----------------------------------------------------------------------------
Perhatian :
Apa yang tertera pada kode sumber ini sebaiknya dipahami terlebih dahulu,
jangan asal 'copy-paste' dan melakukan protes jika tidak sesuai dengan
keinginan.
Yang perlu saya tekankan adalah, bahwa materi yang terdapat dalam kode
sumber ini sekedar demo, 'proof-of-concept' untuk mendukung eksplorasi
lanjutan dari 'Meng-Indonesia-kan MessageDlg' sampai ke batas yang Anda
tentukan sendiri berdasarkan imajinasi dan kreativitas Anda. Ingat, demo
ini belum optimal dan terbaik. Dan tentu saja harapan saya adalah Anda
dapat mengeksplorasi dan mengembangkan jauh lebih baik dari yang ada di
demo ini.
Kelemahan mendasar adalah:
- Ukuran tombol hanya berubah pada saat 'ReplaceResourceString' pertama,
pemanggilan berikutnya tidak mengubah ukuran tombol
-----------------------------------------------------------------------------}
unit CustomMessageDlgDemoUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls;
type
TfrmCustomMessageDlg = class(TForm)
btnStandard: TButton;
btnIndonesian: TButton;
btnContextSave: TButton;
mmoLegend: TMemo;
stbMain: TStatusBar;
btnContextPrint: TButton;
procedure btnStandardClick(Sender: TObject);
procedure btnIndonesianClick(Sender: TObject);
procedure btnContextSaveClick(Sender: TObject);
procedure btnContextPrintClick(Sender: TObject);
private
{ Private declarations }
procedure ReplaceResourceString(RStringRec: PResStringRec; AString: PChar);
procedure SetCustomMessageStandard;
procedure SetCustomMessageIndonesian;
procedure SetCustomMessageContextSave;
procedure SetCustomMessageContextPrint;
public
{ Public declarations }
end;
var
frmCustomMessageDlg: TfrmCustomMessageDlg;
implementation
{$R *.dfm}
uses
Consts;
const
// konstanta default untuk MessageDlg
_SMsgDlgWarning = 'Warning';
_SMsgDlgError = 'Error';
_SMsgDlgInformation = 'Information';
_SMsgDlgConfirm = 'Confirm';
_SMsgDlgYes = '&Yes';
_SMsgDlgNo = '&No';
_SMsgDlgOK = 'OK';
_SMsgDlgCancel = 'Cancel';
_SMsgDlgHelp = '&Help';
_SMsgDlgHelpNone = 'No help available';
_SMsgDlgHelpHelp = 'Help';
_SMsgDlgAbort = '&Abort';
_SMsgDlgRetry = '&Retry';
_SMsgDlgIgnore = '&Ignore';
_SMsgDlgAll = '&All';
_SMsgDlgNoToAll = 'N&o to All';
_SMsgDlgYesToAll = 'Yes to &All';
// konstanta MessageDlg untuk Bahasa Indonesia
_SMsgDlgWarningIndonesian = 'Peringatan';
_SMsgDlgErrorIndonesian = 'Kesalahan';
_SMsgDlgInformationIndonesian = 'Informasi';
_SMsgDlgConfirmIndonesian = 'Konfirmasi';
_SMsgDlgYesIndonesian = '&Ya';
_SMsgDlgNoIndonesian = '&Tidak';
_SMsgDlgOKIndonesian = 'OK';
_SMsgDlgCancelIndonesian = 'Batal';
_SMsgDlgHelpIndonesian = '&Panduan';
_SMsgDlgHelpNoneIndonesian = 'Panduan tidak tersedia';
_SMsgDlgHelpHelpIndonesian = 'Panduan';
_SMsgDlgAbortIndonesian = '&Batal';
_SMsgDlgRetryIndonesian = '&Ulang';
_SMsgDlgIgnoreIndonesian = 'A&cuh';
_SMsgDlgAllIndonesian = '&Semua';
_SMsgDlgNoToAllIndonesian = 'T&idak untuk Semua';
_SMsgDlgYesToAllIndonesian = 'Ya untuk S&emua';
// konstanta MessageDlg untuk konteks Pencetakan
// yang digunakan adalah konfirmasi, mbOK, mbYes dan mbNo
_SMsgDlgWarningContextPrint = 'Peringatan';
_SMsgDlgErrorContextPrint = 'Kesalahan';
_SMsgDlgInformationContextPrint = 'Informasi';
_SMsgDlgConfirmContextPrint = 'Konfirmasi Tujuan Pencetakan';
_SMsgDlgYesContextPrint = '&Printer';
_SMsgDlgNoContextPrint = 'Dokumen PD&F Lebar Yak';
_SMsgDlgOKContextPrint = '&Layar';
_SMsgDlgCancelContextPrint = 'Batal';
_SMsgDlgHelpContextPrint = '&Panduan';
_SMsgDlgHelpNoneContextPrint = 'Panduan tidak tersedia';
_SMsgDlgHelpHelpContextPrint = 'Panduan';
_SMsgDlgAbortContextPrint = '&Batal';
_SMsgDlgRetryContextPrint = '&Ulang';
_SMsgDlgIgnoreContextPrint = 'A&cuh';
_SMsgDlgAllContextPrint = '&Semua';
_SMsgDlgNoToAllContextPrint = 'T&idak untuk Semua';
_SMsgDlgYesToAllContextPrint = 'Ya untuk S&emua';
// konstanta MessageDlg untuk konteks Penyimpanan
// yang digunakan adalah konfirmasi, mbYes dan mbNo
_SMsgDlgWarningContextSave = 'Peringatan';
_SMsgDlgErrorContextSave = 'Kesalahan';
_SMsgDlgInformationContextSave = 'Informasi';
_SMsgDlgConfirmContextSave = 'Konfirmasi Penyimpanan';
_SMsgDlgYesContextSave = '&Simpan';
_SMsgDlgNoContextSave = '&Lanjut Saja';
_SMsgDlgOKContextSave = 'OK';
_SMsgDlgCancelContextSave = 'Batal';
_SMsgDlgHelpContextSave = '&Panduan';
_SMsgDlgHelpNoneContextSave = 'Panduan tidak tersedia';
_SMsgDlgHelpHelpContextSave = 'Panduan';
_SMsgDlgAbortContextSave = '&Batal';
_SMsgDlgRetryContextSave = '&Ulang';
_SMsgDlgIgnoreContextSave = 'A&cuh';
_SMsgDlgAllContextSave = '&Semua';
_SMsgDlgNoToAllContextSave = 'T&idak untuk Semua';
_SMsgDlgYesToAllContextSave = 'Ya untuk S&emua';
procedure TfrmCustomMessageDlg.btnContextPrintClick(Sender: TObject);
begin
SetCustomMessageContextPrint;
end;
procedure TfrmCustomMessageDlg.btnContextSaveClick(Sender: TObject);
begin
SetCustomMessageContextSave;
end;
procedure TfrmCustomMessageDlg.btnIndonesianClick(Sender: TObject);
begin
SetCustomMessageIndonesian;
end;
procedure TfrmCustomMessageDlg.btnStandardClick(Sender: TObject);
begin
SetCustomMessageStandard;
end;
{-- taken from bpCodeReplacement.pas by Bayu Prasetio}
procedure TfrmCustomMessageDlg.ReplaceResourceString(RStringRec: PResStringRec;
AString: PChar);
var
OldProtect: Cardinal;
begin
if RStringRec = nil then Exit;
if VirtualProtectEx(GetCurrentProcess, RStringRec, SizeOf(RStringRec^), PAGE_EXECUTE_READWRITE, OldProtect) then
begin
RStringRec^.Identifier := Integer(AString);
VirtualProtectEx(GetCurrentProcess, RStringRec, SizeOf(RStringRec^), OldProtect, @OldProtect);
end;
end;
procedure TfrmCustomMessageDlg.SetCustomMessageContextPrint;
begin
// sebagai contoh, ubah resource string untuk MessageDlg berdasarkan konteks kejadian
// dalam hal ini adalah proses pencetakan
// mbOK disetarakan tayang ke layar (preview)
// mbYes disetarakan cetak ke printer
// mbNo disetarakan cetak ke dokumen PDF
ReplaceResourceString(@SMsgDlgConfirm, _SMsgDlgConfirmContextPrint);
ReplaceResourceString(@SMsgDlgYes, _SMsgDlgYesContextPrint);
ReplaceResourceString(@SMsgDlgNo, _SMsgDlgNoContextPrint);
ReplaceResourceString(@SMsgDlgOK, _SMsgDlgOKContextPrint);
// gunakan ModalResult dari MessageDlg untuk menentukan tindakan selanjutnya
// hati - hati, Anda tidak dapat menggunakan ShowMessage sekehendak hati
// karena ShowMessage sebenarnya MessageDlg dengan parameter MessageType mtInformation
// dan Buttons [mbOK]. Pahamkan mengapa tombol 'OK' berubah menjadi 'Layar' ?
case MessageDlg('Tentukan tujuan pencetakan dokumen ?', mtConfirmation, [mbOK, mbYes, mbNo], 0) of
mrOK : ShowMessage('Dokumen ditayangkan ke layar');
mrYes : ShowMessage('Dokumen dicetak ke printer');
mrNo : ShowMessage('Dokumen disimpan dalam format .PDF');
end;
end;
procedure TfrmCustomMessageDlg.SetCustomMessageContextSave;
begin
// sebagai contoh, ubah resource string untuk MessageDlg berdasarkan konteks kejadian
// dalam hal ini adalah proses simpan
ReplaceResourceString(@SMsgDlgConfirm, _SMsgDlgConfirmContextSave);
ReplaceResourceString(@SMsgDlgYes, _SMsgDlgYesContextSave);
ReplaceResourceString(@SMsgDlgNo, _SMsgDlgNoContextSave);
ReplaceResourceString(@SMsgDlgCancel, _SMsgDlgCancelContextSave);
MessageDlg('Anda Yakin akan menyimpan dokumen ini ?', mtConfirmation, mbYesNoCancel, 0);
end;
procedure TfrmCustomMessageDlg.SetCustomMessageIndonesian;
begin
// ubah semua resource string untuk MessageDlg ke bahasa Indonesia
ReplaceResourceString(@SMsgDlgWarning, _SMsgDlgWarningIndonesian);
ReplaceResourceString(@SMsgDlgError, _SMsgDlgErrorIndonesian);
ReplaceResourceString(@SMsgDlgInformation, _SMsgDlgInformationIndonesian);
ReplaceResourceString(@SMsgDlgConfirm, _SMsgDlgConfirmIndonesian);
ReplaceResourceString(@SMsgDlgYes, _SMsgDlgYesIndonesian);
ReplaceResourceString(@SMsgDlgNo, _SMsgDlgNoIndonesian);
ReplaceResourceString(@SMsgDlgOK, _SMsgDlgOKIndonesian);
ReplaceResourceString(@SMsgDlgCancel, _SMsgDlgCancelIndonesian);
ReplaceResourceString(@SMsgDlgHelp, _SMsgDlgHelpIndonesian);
ReplaceResourceString(@SMsgDlgHelpNone, _SMsgDlgHelpNoneIndonesian);
ReplaceResourceString(@SMsgDlgHelpHelp, _SMsgDlgHelpHelpIndonesian);
ReplaceResourceString(@SMsgDlgAbort, _SMsgDlgAbortIndonesian);
ReplaceResourceString(@SMsgDlgRetry, _SMsgDlgRetryIndonesian);
ReplaceResourceString(@SMsgDlgIgnore, _SMsgDlgIgnoreIndonesian);
ReplaceResourceString(@SMsgDlgAll, _SMsgDlgAllIndonesian);
ReplaceResourceString(@SMsgDlgNoToAll, _SMsgDlgNoToAllIndonesian);
ReplaceResourceString(@SMsgDlgYesToAll, _SMsgDlgYesToAllIndonesian);
MessageDlg('Anda Yakin akan menyimpan dokumen ini ?', mtConfirmation, mbYesNoCancel, 0);
end;
procedure TfrmCustomMessageDlg.SetCustomMessageStandard;
begin
// ubah semua resource string untuk MessageDlg ke default
ReplaceResourceString(@SMsgDlgWarning, _SMsgDlgWarning);
ReplaceResourceString(@SMsgDlgError, _SMsgDlgError);
ReplaceResourceString(@SMsgDlgInformation, _SMsgDlgInformation);
ReplaceResourceString(@SMsgDlgConfirm, _SMsgDlgConfirm);
ReplaceResourceString(@SMsgDlgYes, _SMsgDlgYes);
ReplaceResourceString(@SMsgDlgNo, _SMsgDlgNo);
ReplaceResourceString(@SMsgDlgOK, _SMsgDlgOK);
ReplaceResourceString(@SMsgDlgCancel, _SMsgDlgCancel);
ReplaceResourceString(@SMsgDlgHelp, _SMsgDlgHelp);
ReplaceResourceString(@SMsgDlgHelpNone, _SMsgDlgHelpNone);
ReplaceResourceString(@SMsgDlgHelpHelp, _SMsgDlgHelpHelp);
ReplaceResourceString(@SMsgDlgAbort, _SMsgDlgAbort);
ReplaceResourceString(@SMsgDlgRetry, _SMsgDlgRetry);
ReplaceResourceString(@SMsgDlgIgnore, _SMsgDlgIgnore);
ReplaceResourceString(@SMsgDlgAll, _SMsgDlgAll);
ReplaceResourceString(@SMsgDlgNoToAll, _SMsgDlgNoToAll);
ReplaceResourceString(@SMsgDlgYesToAll, _SMsgDlgYesToAll);
MessageDlg('Anda Yakin akan menyimpan dokumen ini ?', mtConfirmation, mbYesNoCancel, 0);
end;
end.
Dan sebagai catatan, ada kelemahan yang perlu diketahui perihal trik, yaitu ukuran tombol hanya berubah pada saat ‘ReplaceResourceString’ pertama, pemanggilan berikutnya tidak mengubah ukuran tombol.
Ok, seperti yang telah saya tulis komentar di kode sumber, “harapan saya adalah Anda dapat mengeksplorasi dan mengembangkan jauh lebih baik dari yang ada di demo ini”. Saya sengaja membuat demo ini belum optimal, jadi silahkan gunakan logika, kreativitas dan imajinasi Anda.
Semoga bermanfaat.


@deLogic
ehmm.. ada yg masih mengganjal dibenakku..
untuk text di messageDlg, mungkinkah Alignmentnya dibuat menjadi center..
karena defaultnya kan left.. ????
Jika berdasarkan cakupan kode di atas, tentu saja tidak bisa. Namun fitur tsb bisa dilakukan, tentu saja dgn menambah trik lain lagi. Tunggu saja tanggal mainnya.
Atau jika anda tdk sabar, saya berikan kata kuncinya: Code Redirect dan atau Overloading Function.
Hehehe.. dengan penuh kesabaran daku menunggu tanggal mainnya..
absolutely i’ll wait your post