⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zmisc3.htm

📁 对于学习很有帮助
💻 HTM
📖 第 1 页 / 共 3 页
字号:
<!-- This document was created with HomeSite v2.0 -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">

<HTML>
<HEAD>
	<TITLE>UDDF - Misc</TITLE>
	<META NAME="Description" CONTENT="Miscellaneous section of the Delphi Developers FAQ" >
	<META NAME="KeyWords" CONTENT="" >

</HEAD>

<BODY  BGCOLOR="#FFFFFF">
<CENTER>
<IMG SRC="../images/uddf.jpg"> </CENTER>
<HR SIZE="6" color="#00FF00">


<CENTER><FONT SIZE="7" FACE="Arial Black" COLOR="RED">Miscellaneous Part 3</FONT></CENTER>

<P><H1><A NAME="zmisc30">Avoiding using stale pointers</P></A></H1>
<P><I>"David S. Becker" &lt;dsb@plaza.ds.adp.com></I></P>

I've written a very simple unit, and devised some simple methods, to help
prevent the usage of stale pointers.  My biggest recommendation is to add
an 'initialization' section to ALL UNITS WHICH CONTAIN POINTER OR OBJECT
VARIABLES and set all the pointers (object variables are really pointers
too) to nil.  This will ensure that the pointers are all nilified before
they are ever used.  Then, simply reset pointers to nil after freeing them.
 My unit contains a Nilify() function for setting pointers to nil, as well
as special versions of Free, Dispose, and FreeMem (called NilXXX) which
test for nil before freeing memory, and resets the pointer to nil once it
has been freed.  I've also included a special version of Assigned(), called
IsNil(), which takes a const parameter instead of a var parameter, which
means you can use it on properties, etc. <P>

This unit, of course, does nothing to the VCL, so you can still get stale
pointers back from the VCL...  But strict adherence to the functions in
this unit should help ensure YOU don't make a mistake.  The only condition
on its use/distribution is that you forward any changes or suggestions you
might have to me.  Use it and program in good health! <P>


<HR><PRE>unit Pointers;

{
  Author: David S. Becker (dsb@plaza.ds.adp.com)
  Date: 1/27/97
  Copyright: None
  Distribution Rights:  Free, unlimited use, provided you forward any and all
    changes or suggestions you have to me.

  This unit was created to aid in the managment of pointers and objects.  Since
  the compiler does not initialize pointers or objects to nil, and does not set
  them to nil when freed, it is possible to accidentally reference stale
  pointers.  For this reason, I recommend you add an 'initialization' section to
  all units and call Nilify() on all pointers/objects in that unit.  This
  will ensure that all pointers/objects start off as nil.  Furthermore, you
  should use the NilFree (for objects), NilDispose (for pointers created with
  New), and NilFreeMem (for pointers created with GetMem) instead of their
  standard counterparts.  These procedures are safe to call on nil pointer/
  objects, as they check for nil before performing any action.  After freeing
  the memory allocated to the pointer/object, they reset the pointer to nil.  If
  you are strict in your use of these procedures, your risk of accessing stale
  pointer is greatly reduced.  (Of course, you can still get stale pointers from
  the VCL as it obviously doesn't use these functions.)
}

{==============================================================================}
interface

{------------------------------------------------------------------------------}
{ Checks a pointer against nil }
{ NOTE: This function differs from Assigned() in that Assigned() requires a }
{ variable, whereas IsNil() does not.                                       }
function IsNil(const p: Pointer): Boolean;
{ Sets a pointer to nil }
procedure Nilify(var p);
{ Frees a non-nil object, then sets it to nil }
procedure NilFree(o: TObject);
{ Frees a non-nil pointer created by New, then sets it to nil }
procedure NilDispose(var p: Pointer);
{ Frees a non-nil pointer, then sets it to nil }
procedure NilFreeMem(var p: Pointer; size: Word);

{==============================================================================}
implementation

{------------------------------------------------------------------------------}
function IsNil(const p: Pointer): Boolean;
begin
  Result := (p = nil);
end;

{------------------------------------------------------------------------------}
procedure Nilify(var p);
begin
  Pointer(p) := nil;
end;

{------------------------------------------------------------------------------}
procedure NilFree(o: TObject);
begin
  if not IsNil(o) then begin
    o.Free;
    Nilify(o);
  end;
end;

{------------------------------------------------------------------------------}
procedure NilDispose(var p: Pointer);
begin
  if not IsNil(p) then begin
    Dispose(p);
    Nilify(p);
  end;
end;

{------------------------------------------------------------------------------}
procedure NilFreeMem(var p: Pointer; size: Word);
begin
  if not IsNil(p) then begin
    FreeMem(p,size);
    Nilify(p);
  end;
end;

end.
</PRE><HR>
<P><H1><A NAME="zmisc31">Multi Language Applications</P></A></H1>
<P><I>Eddie Shipman &lt;eshipman@inetport.com></I></P>

For anyone needing to do multi-language apps and don't want to
write a lot of code checking  what language the program is 
running, see below. I compiled a stringtable resource into my exe and
this is how I used it for multi-language dialogs. <P>

Instead of using the Runtime directives to check what language, I used a
runtime 
variable to set the index for the messages into the stringtable and then
load the 
messages from there depending upon the language.
You could also create different stringtables for each language and then
compiling 
them in by using the compile directives. <P>

Here is some example code, give it a try: <P>

<HR><PRE>unit French1;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls, IniFiles;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormActivate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  StringIndex : Integer;
implementation

{$R *.DFM}

{$R MULTLANG.RES}

{ Here is the way the resource file for this project looks:
 1, "Attention"
 2, "No Condition definition selected!"
 3, "Always"
 4, "Cannot delete the 'always' condition."
 5, "Confirmation"
 6, "Delete the condition?"
 7, "Yes"
 8, "No"
 9, "Attention"
 10, "Pas de condition Selectionn閑"
 11, "Toulours"
 12, "Ne peux effacer la condition 'Toujours'"
 13, "Confirmation"
 14, "Effacer cette condition?"
 15, "&Oui"
 16, "&Non"
}

procedure TForm1.FormActivate(Sender: TObject);
var
  {inifile : TIniFile; Optional}
  ProgramLanguage : String;
begin
  { Here, I just set it to French }
   ProgramLanguage := 'fra';
  { You can optionally get the language from Win.INI:}
  {inifile := TInifile.Create('WIN.INI');
   ProgramLanguage := inifile.ReadString('intl', 'sLanguage', 'enu');
   inifile.Free;}
  { Forgive me if I leave out any languages, Tthese are th only ones
    in my setup.inf for my copy of Windows.

   dan = Danish
   nld = Dutch
   enu = English (American)
   eng = English (International)
   fin = Finnish
   fra = French
   frc = French Canadian
   deu = German
   isl = Icelandic
   ita = Italian
   nor = Norwegian
   ptg = Portuguese
   esp = Spanish
   esn = Spanish (Modern)
   sve = Swedish

}
   if ProgramLanguage = 'enu' then
   begin
      StringIndex := 0;
   end
   else
      if ProgramLanguage = 'fra' then
      begin
         StringIndex := 8;
      end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
   i,j,k : integer;
   DialogForm : tform;
begin
   Application.NormalizeTopMosts;
   {no Condition Selected!}
   DialogForm := CreateMessageDialog(LoadStr(StringIndex+2),mtWarning,[mbOK]);
   {Attention}
   DialogForm.caption := LoadStr(StringIndex + 1);
   DialogForm.showmodal;
   Application.RestoreTopMosts;
   {Cannot Delete the 'always' condition}
   DialogForm := CreateMessageDialog(LoadStr(StringIndex+4),mtWarning,[mbOK]);
   {Always}
   DialogForm.caption := LoadStr(StringIndex + 3);
   DialogForm.showmodal;
   Application.RestoreTopMosts;
   {Delete the condition?}
   DialogForm := CreateMessageDialog(LoadStr(StringIndex+6),mtInformation, [mbYes, mbNo]);
   {confirmation}
   DialogForm.caption := LoadStr(StringIndex + 5);
   for j := 0 to DialogForm.controlCount-1 do
   begin
      if DialogForm.controls[j] is tButton then
         with tButton(DialogForm.controls[j]) do
         begin
            if caption = '&Yes' then caption := LoadStr(StringIndex+7);
            if caption = '&No' then caption := LoadStr(StringIndex+8);
          end;
    end;
   DialogForm.showmodal;
end;

end.
</PRE><HR>

<P><H1><A NAME="zmisc32">Associated Executable</P></A></H1>
<P><I>Michael Ax &lt;ax@HREF.COM&gt;</I></P>


<HR><PRE>unit UcShell;

{ Author: Michael Ax   http://www.axsystems.com/
  Copyright (c) 1995..1997 Michael Ax.  All Rights Reserved.
  This source code is part of TPack from HREF Tools Corp.
  Obtain purchasing and additional information by sending an email to
  software@href.com (any subject, any message)...
  or visit us on the web at http://www.href.com/software/
}

interface

uses Classes, SysUtils, Windows, ShellApi, Forms;

{---------------------------------------------------------------}

function WinExecutableName(const AssociatedFile:string):String;

procedure WinShellOpen(const AssociatedFile:string);
procedure WinShellPrint(const AssociatedFile:string);
procedure WinShellExecute(const Operation,AssociatedFile:string);

{---------------------------------------------------------------}

implementation

Const
  cStrBufSize= 80;

{---------------------------------------------------------------}


function WinExecutableName(const AssociatedFile:string):String;
//HINSTANCE FindExecutable(
//    LPCTSTR lpFile,   // pointer to string for filename
//    LPCTSTR lpDirectory,      // pointer to string for default directory
//    LPTSTR lpResult   // pointer to buffer for string for executable file
on return
//   );
begin
  SetLength(result,cStrBufSize); //ucshell
  FindExecutable(pchar(AssociatedFile),'',pchar(result));
  SetLength(result,strlen(pchar(result)));
end;

//

procedure WinShellExecute(const Operation,AssociatedFile:string);
var
  a1:string;
begin
  a1:=Operation;
  if a1='' then
    a1:='open';
  ShellExecute(
    application.handle			//hWnd: HWND
    ,pchar(a1)				//Operation: PChar
    ,pchar(AssociatedFile)		//FileName: PChar
    ,''						//Parameters: PChar
    ,''						//Directory: PChar
    ,SW_SHOWNORMAL		//ShowCmd: Integer
    );
//  GetLastErrorString(0);		//ucdialog
end;

procedure WinShellPrint(const AssociatedFile:string);
begin
  WinShellExecute('print',AssociatedFile);
end;

procedure WinShellOpen(const AssociatedFile:string);
begin
  WinShellExecute('open',AssociatedFile);
end;

{-----------------------------------------------------------------}
end.
</PRE><HR>

<P><H1><A NAME="zmisc33">MAPI and MS Exchange</P></A></H1>
<P><I>Keith Anderson &lt;keith@PURESCIENCE.COM&gt;</I></P>

Use the following to login:

<HR><PRE>  MapiLogon(application.handle,nil,nil,mapi_use_default,0,@mapihandle)</PRE><HR>

Then use the following to send your message:

<HR><PRE>  MapiSendMail(mapihandle, 0,MapiMessage,0, 0);</PRE><HR>

Make sure the SUBJECT, RECIP and NOTTEXT fields are complete in the
MapiMessage structure or the message won't be sent. <P>

Also make sure Exchange is running using the GetWindowHandle API function,
and if it's not, use ShellExecute (or whatever) to launch it first.


<P><H1><A NAME="zmisc34">Constucting Object Variables</P></A></H1>
<P><I>From: richardp@calweb.com (Coyote)</I></P>

In the past few days there have been more than a few questions on this 
group indicating a lack of understanding about object instantiation. I'm 
guessing that these have been beginners, but in one case the questioner 
was taking a class on Delphi. I'd hope that an instructor would at least 
*try* to explain the subject. <P>

Anyway, for all of you having pointer errors, exceptions, and GPFs, take 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -