AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi Fehlermeldung mit $IMPORTEDDATA bei eigener MessageBox
Thema durchsuchen
Ansicht
Themen-Optionen

Fehlermeldung mit $IMPORTEDDATA bei eigener MessageBox

Offene Frage von "VizeTE"
Ein Thema von VizeTE · begonnen am 21. Nov 2007
Antwort Antwort
VizeTE

Registriert seit: 31. Dez 2002
178 Beiträge
 
Delphi 5 Enterprise
 
#1

Fehlermeldung mit $IMPORTEDDATA bei eigener MessageBox

  Alt 21. Nov 2007, 15:41
Hallo,

ich möchte mir eine eigene MessageBox basteln und diese zu einem eigenen (bereits bestehenden) Package hinzufügen. Dazu habe ich die Box zunächst einmal als Unit in einem eigenen Projekt erstellt da es sich so einfacher debuggen läßt. Es hat auch alles prima funktioniert. Nun habe ich die Unit in ein bereits bestehendes Package eingebunden.

Dies wurde mit einem Fehler folgenden Types quittiert:
Für den Zugriff auf <Name> und Unit <Name> wird die importierte Datenreferenz ($G) benötigt.

Konkret waren es folgende:
Zitat:
[Fehler] Für den Zugriff auf 'SMsgDlgYes' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
[Fehler] Für den Zugriff auf 'SMsgDlgNo' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
[Fehler] Für den Zugriff auf 'SMsgDlgOK' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
[Fehler] Für den Zugriff auf 'SMsgDlgCancel' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
[Fehler] Für den Zugriff auf 'SMsgDlgAbort' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
[Fehler] Für den Zugriff auf 'SMsgDlgRetry' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
[Fehler] Für den Zugriff auf 'SMsgDlgIgnore' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
[Fehler] Für den Zugriff auf 'SMsgDlgAll' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
[Fehler] Für den Zugriff auf 'SMsgDlgNoToAll' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
[Fehler] Für den Zugriff auf 'SMsgDlgYesToAll' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
[Fehler] Für den Zugriff auf 'SMsgDlgHelp' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
[Fehler] Für den Zugriff auf 'SMsgDlgWarning' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
[Fehler] Für den Zugriff auf 'SMsgDlgError' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
[Fehler] Für den Zugriff auf 'SMsgDlgInformation' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
[Fehler] Für den Zugriff auf 'SMsgDlgConfirm' von Unit 'AvMsgBox' wird die importierte Datenreferenz ($G) benötigt
Die Delphi-Hilfe habe ich so verstanden, dass dieser Compiler-Schalter aktiviert werden muß wenn Variabeln aus einem anderen Package verwendet werden sollen. Als Lösung wird mir folgendes angeboten:
Zitat:
Das Problem läßt sich am einfachsten durch eine erneute Compilierung der fehlerverursachenden Unit mit aktivierter Option $IMPORTEDDATA lösen.
Jedoch hat das aktivieren des Schalters $G bzw. $IMPORTEDDATA nicht geholfen.

Hier mal der Quellcode der Unit (kann beim ersten lesen übersprungen werden ):
Delphi-Quellcode:
unit AvMsgBox;

{$G+}
{$IMPORTEDDATA ON}

interface

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

const
  MENUID_COPY_TO_CLIPBOARD = 998;

type
  TAvMessageBox = class(TForm)
    MsgLabel: TLabel;
    procedure FormDestroy(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  private
    procedure SetMsgText(const Value: string);
  protected
    FButtons : TMsgDlgButtons;
    FCaption : string;
    FDefaultBtn : TMsgDlgBtn;
    FDelaySecs : integer;
    FDelayTimer : TTimer;
    FDlgType : TMsgDlgType;
    FIconImage : TImage;

    function GetMsgLabelWidth : integer;
    function GetMsgLabelHeight : integer;

    procedure AddSystemMenuItem;
    procedure CreateButtons;
    procedure CreateIcon;
    procedure OnDelayTimerTimer(Sender: TObject);
    procedure SetButtonStates(Enabled: boolean);
    procedure SetCaption;
  public
    procedure WndProc(var Msg: TMessage); override;

    property Buttons : TMsgDlgButtons write FButtons;
    property DefaultBtn : TMsgDlgBtn write FDefaultBtn;
    property DelaySecs : integer write FDelaySecs;
    property DlgType : TMsgDlgType write FDlgType;
    property MsgText : string write SetMsgText;
  end;

function AvMessageBox(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons): Word; overload;
function AvMessageBox(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; DefaultBtn: TMsgDlgBtn; DelaySecs: integer): Word; overload;

implementation

uses
  Clipbrd,
  Consts,
  Math;

{$R *.DFM}

//resourcestring //hiermit funktionierts aber eigentlich sollen der Werte aus der Delphi-Unit "Consts" verwendet werden
// SMsgDlgWarning = 'Warnung';
// SMsgDlgError = 'Fehler';
// SMsgDlgInformation = 'Information';
// SMsgDlgConfirm = 'Bestätigung';
// SMsgDlgYes = '&Ja';
// SMsgDlgNo = '&Nein';
// SMsgDlgOK = 'OK';
// SMsgDlgCancel = 'Abbrechen';
// SMsgDlgHelp = '&Hilfe';
// SMsgDlgHelpNone = 'Keine Hilfe verfügbar';
// SMsgDlgHelpHelp = 'Hilfe';
// SMsgDlgAbort = '&Abbrechen';
// SMsgDlgRetry = '&Wiederholen';
// SMsgDlgIgnore = '&Ignorieren';
// SMsgDlgAll = '&Alle';
// SMsgDlgNoToAll = '&Alle Nein';
// SMsgDlgYesToAll = 'A&lle Ja';

var
  ButtonCaptions: array[TMsgDlgBtn] of Pointer = (
    @SMsgDlgYes,
    @SMsgDlgNo,
    @SMsgDlgOK,
    @SMsgDlgCancel,
    @SMsgDlgAbort,
    @SMsgDlgRetry,
    @SMsgDlgIgnore,
    @SMsgDlgAll,
    @SMsgDlgNoToAll,
    @SMsgDlgYesToAll,
    @SMsgDlgHelp
  );

  ButtonNames: array[TMsgDlgBtn] of string = (
    'Yes',
    'No',
    'OK',
    'Cancel',
    'Abort',
    'Retry',
    'Ignore',
    'All',
    'NoToAll',
    'YesToAll',
    'Help'
  );
  Captions: array[TMsgDlgType] of Pointer = (
    @SMsgDlgWarning,
    @SMsgDlgError,
    @SMsgDlgInformation,
    @SMsgDlgConfirm,
    nil
  );
  IconIDs: array[TMsgDlgType] of PChar = (
    IDI_EXCLAMATION,
    IDI_HAND,
    IDI_ASTERISK,
    IDI_QUESTION,
    nil
  );
  ModalResults: array[TMsgDlgBtn] of Integer = (
    mrYes,
    mrNo,
    mrOk,
    mrCancel,
    mrAbort,
    mrRetry,
    mrIgnore,
    mrAll,
    mrNoToAll,
    mrYesToAll,
    0
  );

function AvMessageBox(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons): Word;
begin
  Result := AvMessageBox(Msg, DlgType, Buttons, mbOK, 0);
end;

function AvMessageBox(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; DefaultBtn: TMsgDlgBtn; DelaySecs: integer): Word;
var
  AMsgBox : TAvMessageBox;
begin
  Application.CreateForm(TAvMessageBox, AMsgBox);
  try
    AMsgBox.MsgText := Msg;
    AMsgBox.DlgType := DlgType;
    AMsgBox.Buttons := Buttons;
    AMsgBox.DelaySecs := DelaySecs;
    AMsgBox.DefaultBtn := DefaultBtn;
    Result := AMsgBox.ShowModal;
  finally
    AMsgBox.Release;
    AMsgBox := nil;
  end;
end;

procedure TAvMessageBox.AddSystemMenuItem;
var
  AMenuHandle : THandle;
begin
  AMenuHandle := GetSystemMenu(Self.Handle, false);
  if AMenuHandle <> 0 then
  begin
    InsertMenu(AMenuHandle, 0, MF_ENABLED, MENUID_COPY_TO_CLIPBOARD, PChar('in Zwischenablage kopieren'));
    DrawMenuBar(AMenuHandle);
  end;
end;

procedure TAvMessageBox.CreateButtons;
const
  BTN_SPACE = 4;
var
  AIndex : TMsgDlgBtn;
  ABtn : TBitBtn;
  ABtnCnt : integer;
  ABtnLeft : integer;
  ABtnWidth : integer;
  ABtnWidthSum : integer;
  ACancelBtn : TMsgDlgBtn;
begin
  ABtnCnt := 0;
  ABtnWidth := 65;

  //Anzahl der Schaltflächen ermitteln
  Self.Canvas.Font := Self.Font;
  for AIndex := Low(TMsgDlgBtn) to High(TMsgDlgBtn) do
    if AIndex in FButtons then
    begin
      Inc(ABtnCnt);
      ABtnWidth := Max(ABtnWidth, Self.Canvas.TextWidth(LoadResString(ButtonCaptions[AIndex])) + 8);
    end;

  ABtnWidthSum := (ABtnWidth * ABtnCnt) + (BTN_SPACE * Pred(ABtnCnt));
  if ABtnWidthSum > ClientWidth then
    ClientWidth := ABtnWidthSum + 2 * BTN_SPACE;

  //die linke Koordinate der ersten Schaltfläche setzen
  ABtnLeft := (Self.ClientWidth - ABtnWidthSum) div 2;

  //Default-Buttno ermitteln
  if FDefaultBtn = mbOK then //wenn was anderes als mbOK gesetzt ist dann war das Absicht
    if mbOk in FButtons then
      FDefaultBtn := mbOk
    else if mbYes in FButtons then
      FDefaultBtn := mbYes
    else
      FDefaultBtn := mbRetry;

  //Cancel-Button ermitteln
  if mbCancel in FButtons then
    ACancelBtn := mbCancel
  else if mbNo in FButtons then
    ACancelBtn := mbNo
  else
    ACancelBtn := mbOk;

  //Schaltflächen erstellen, beschriften und platzieren
  for AIndex := Low(TMsgDlgBtn) to High(TMsgDlgBtn) do
    if AIndex in FButtons then
    begin
      ABtn := TBitBtn.Create(Self);
      ABtn.Name := ButtonNames[AIndex];
      ABtn.Parent := Self;
      ABtn.Caption := LoadResString(ButtonCaptions[AIndex]);
      ABtn.ModalResult := ModalResults[AIndex];
      ABtn.Enabled := false; //Buttons dürfen erst aktiviert werden wenn Formular sichtbar ist damit der Default-Button vorselektiert wird => FormAfterShow
      if AIndex = FDefaultBtn then
        ABtn.Default := true;
      if AIndex = ACancelBtn then
        ABtn.Cancel := true;

      ABtn.Left := ABtnLeft;
      ABtn.Top := ClientHeight - 36;
      ABtn.Width := ABtnWidth;
      ABtn.Height := 25;

      ABtnLeft := ABtnLeft + ABtnWidth + BTN_SPACE;
    end;
end;

procedure TAvMessageBox.CreateIcon;
var
  IconID : PChar;
begin
  IconID := IconIDs[FDlgType];
  if IconID <> nil then
  begin
    FIconImage := TImage.Create(Self);
    FIconImage.Name := 'IconImage';
    FIconImage.Parent := Self;
    FIconImage.Picture.Icon.Handle := LoadIcon(0, IconID);
    FIconImage.SetBounds(16, Max(1, MsgLabel.Height div 2 - 16 + MsgLabel.Top), 32, 32);
  end;
end;

procedure TAvMessageBox.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose := FDelaySecs <= 0;
end;

procedure TAvMessageBox.FormCreate(Sender: TObject);
begin
  FDefaultBtn := mbOK;

  if Application.Icon.Handle <> 0 then
    SendMessage(Handle, WM_SETICON, ICON_BIG, Application.Icon.Handle);

  AddSystemMenuItem;
end;

procedure TAvMessageBox.FormDestroy(Sender: TObject);
begin
  FreeAndNil(FIconImage);
end;

procedure TAvMessageBox.FormShow(Sender: TObject);
var
  AValue : integer;
begin
  AValue := Max(144, GetMsgLabelWidth + 3);
  Width := Width + (AValue - MsgLabel.Width);

  AValue := GetMsgLabelHeight;
  Height := Max(125, Height + (AValue - MsgLabel.Height));

  SetCaption;
  CreateIcon;
  CreateButtons;

  if FDelaySecs > 0 then
  begin
    FDelayTimer := TTimer.Create(Self);
    FDelayTimer.Interval := 1000;
    FDelayTimer.Enabled := true;
    FDelayTimer.OnTimer := OnDelayTimerTimer;

    Inc(FDelaySecs); //sonst fängt der Timer scheinbar schon bei FDelaySecs-1 an
  end;

  if FDelaySecs <= 0 then
    SetButtonStates(true);
end;

function TAvMessageBox.GetMsgLabelHeight: integer;
var
  AStrList : TStringList;
begin
  AStrList := TStringList.Create;
  AStrList.Text := MsgLabel.Caption;
  MsgLabel.Canvas.Font := MsgLabel.Font;

  Result := MsgLabel.Canvas.TextHeight(MsgLabel.Caption);
  Result := (Result + 2) * Max(1, AStrList.Count);

  AStrList.Free;
end;

function TAvMessageBox.GetMsgLabelWidth: integer;
var
  AIndex : integer;
  AStrList : TStringList;
begin
  Result := 0;

  AStrList := TStringList.Create;
  AStrList.Text := MsgLabel.Caption;

  MsgLabel.Canvas.Font := MsgLabel.Font;
  for AIndex := 0 to Pred(AStrList.Count) do
    Result := Max(Result, MsgLabel.Canvas.TextWidth(AStrList[AIndex]));

  AStrList.Free;
end;

procedure TAvMessageBox.OnDelayTimerTimer(Sender: TObject);
begin
  if FDelaySecs > 1 then
  begin
    Dec(FDelaySecs);
    Caption := FCaption + ' - ' + IntToStr(FDelaySecs);
  end else
  begin
    FDelayTimer.Enabled := false;
    Caption := FCaption;
    Dec(FDelaySecs);
    SetButtonStates(true);
  end;
end;

procedure TAvMessageBox.SetButtonStates(Enabled: boolean);
var
  AIndex : integer;
begin
  for AIndex := 0 to Pred(ComponentCount) do
    if Components[AIndex] is TBitBtn then
    begin
      TBitBtn(Components[AIndex]).Enabled := true;
      if (ModalResults[FDefaultBtn] = TBitBtn(Components[AIndex]).ModalResult) and
         (TBitBtn(Components[AIndex]).CanFocus) then
        TBitBtn(Components[AIndex]).SetFocus;
    end;
end;

procedure TAvMessageBox.SetCaption;
begin
  if FDlgType <> mtCustom then
    FCaption := LoadResString(Captions[FDlgType])
  else
    FCaption := Application.Title;
  Caption := FCaption;
end;

procedure TAvMessageBox.SetMsgText(const Value: string);
begin
  MsgLabel.Caption := Value;
end;

procedure TAvMessageBox.WndProc(var Msg: TMessage);
begin
  inherited;

  if Msg.Msg = WM_SYSCOMMAND then
    if Msg.WParam = MENUID_COPY_TO_CLIPBOARD then
    begin
      Clipboard.Clear;
      Clipboard.HasFormat(CF_TEXT);
      Clipboard.AsText := 'Anwendung: ' + Application.Title + #13#10
                             + 'Zeitstempel: ' + DateTimeToStr(Now) + #13#10
                             + 'Meldung'#13#10'======='#13#10 + MsgLabel.Caption;
    end;
end;

end.
Vor dem Interfaceabschnitt habe ich mit den Compilerschaltern $G und $IMPORTEDDATA rumgespielt. Habe leider keine funktionierende "Kombination" gefunden. ($G-, $G+, $IMPORTEDDATA ON, $IMPORTEDDATA OFF) In der Package-Unit ist folgender Schalter enthalten: {$IMPORTEDDATA ON}

Im Implementationsabschnitt habe ich den resourcestring-Block auskommentiert. Wenn ich den aktiviere dann funktionierts weil der Compiler nicht mehr versucht die Daten aus der Delphi-Unit "Consts" zu holen. Aber das sollte doch gehen?!
Ach ja ... ist Delphi5
Angehängte Dateien
Dateityp: dfm avmsgbox_853.dfm (922 Bytes, 3x aufgerufen)
Dateityp: pas avmsgbox_121.pas (10,3 KB, 6x aufgerufen)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:15 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz