عرض شاشة البداية في دلفي عندما يكون الموضوع الرئيسي مشغولا

StackOverflow https://stackoverflow.com/questions/388506

سؤال

أرغب في عرض شاشة البداية أثناء تحميل التطبيق. ومع ذلك، تقوم بعض مكونات الطرف الثالث بمنح الخيط الرئيسي أثناء بدء التشغيل لعدة ثوان، مما يؤدي إلى تحديث جميع الأشكال. هل من الممكن الحصول على شاشة البداية مع مؤشر ترابط خاص بهذا وسوف يتم تحديثه أيضا عند مشغول الخيط الرئيسي؟

التطبيق هو Win32 و Delphi الإصدار 2007.

تحرير: أحاول تجنب تأثير "شاشة البداية غير المستمرة"، والتي تحدث إذا كانت بعض النوافذ الأخرى (من التطبيقات الأخرى) موجودة في الجزء العلوي من شاشة البداية، على سبيل المثال Alt-tabbing إلى تطبيق آخر والظهر.

هل كانت مفيدة؟

المحلول

يمكنك تشغيل شاشة البداية في مؤشر ترابط آخر، ولكن بعد ذلك، ستحتاج إلى استخدام مكالمات Windows API الخام أو مكتبة جهة خارجية (مثل مكتبة الأجسام الرئيسية) أن ينفذ فصول تشبه VCL. ومع ذلك، لا يمكن الوصول إلى VCL Stuffs من موضوع Splash.

إذا ذهبت إلى هذا الطريق (الذي لا أعتقد أنه يجب عليك، لأنه الكثير من العمل للحصول على مكسب صغير)، تأكد من مراعاة القواعد حول وصول Windows API من مؤشرات ترابط متعددة. جوجل على سبيل المثال ل "ترابط واجهة المستخدم" لمزيد من المعلومات.

يحرر:

لم أكن على علم بذلك من قبل، ولكن هناك بالفعل مكون ينفذ الخيوط Splashscreen ل دلفي على codecentral. باستخدام هذا المكون قد يكون (لم تجربه) في الواقع يكون من السهل الحصول على شاشة البداية في مؤشر ترابط مختلف، ولكن التحذير ضد وصول VCL من المواضيع الثانوية.

نصائح أخرى

في الواقع Winapi طريقة بسيطة للغاية طالما كنت تستخدم موارد الحوار. تحقق من هذا (يعمل حتى على D7 و XP):

type
  TDlgThread = class(TThread)
  private
    FDlgWnd: HWND;
    FCaption: string;
  protected
    procedure Execute; override;
    procedure ShowSplash;
  public
    constructor Create(const Caption: string);
  end;

{ TDlgThread }

// Create thread for splash dialog with custom Caption and show the dialog
constructor TDlgThread.Create(const Caption: string);
begin
  FCaption := Caption;
  inherited Create(False);
  FreeOnTerminate := True;
end;

procedure TDlgThread.Execute;
var Msg: TMsg;
begin
  ShowSplash;
  // Process window messages until the thread is finished
  while not Terminated and GetMessage(Msg, 0, 0, 0) do
  begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  end;
  EndDialog(FDlgWnd, 0);
end;

procedure TDlgThread.ShowSplash;
const
  PBM_SETMARQUEE = WM_USER + 10;
  {$I 'Dlg.inc'}
begin
  FDlgWnd := CreateDialogParam(HInstance, MakeIntResource(IDD_WAITDLG), 0, nil, 0);
  if FDlgWnd = 0 then Exit;
  SetDlgItemText(FDlgWnd, IDC_LABEL, PChar(FCaption));           // set caption
  SendDlgItemMessage(FDlgWnd, IDC_PGB, PBM_SETMARQUEE, 1, 100);  // start marquee
end;

procedure TForm1.Button3Click(Sender: TObject);
var th: TDlgThread;
begin
  th := TDlgThread.Create('Connecting to DB...');
  Sleep(3000); // blocking wait
  th.Terminate;
end;

بالطبع يجب عليك إعداد مورد الحوار (Dlg.rc) وإضافته إلى مشروعك:

#define IDD_WAITDLG 1000
#define IDC_PGB 1002
#define IDC_LABEL 1003

#define PBS_SMOOTH  0x00000001
#define PBS_MARQUEE 0x00000008

IDD_WAITDLG DIALOGEX 10,10,162,33
STYLE WS_POPUP|WS_VISIBLE|WS_DLGFRAME|DS_CENTER
EXSTYLE WS_EX_TOPMOST
BEGIN
  CONTROL "",IDC_PGB,"msctls_progress32",WS_CHILDWINDOW|WS_VISIBLE|PBS_SMOOTH|PBS_MARQUEE,9,15,144,15
  CONTROL "",IDC_LABEL,"Static",WS_CHILDWINDOW|WS_VISIBLE,9,3,144,9
END

لاحظ هؤلاء PBS_* يحدد. اضطررت إلى إضافتها لأن دلفي 7 لا يعرف شيئا من هذه الثوابت. وتعريف الثوابت (Dlg.inc)

const IDD_WAITDLG = 1000;
const IDC_PGB = 1002;
const IDC_LABEL = 1003;

(يمكنني استخدام محرر مورد Radasm الذي ينشئ الملف تلقائيا).

ما نحصل عليه تحت XP

ما هو أفضل بهذه الطريقة مقارنة مع الحيل VCL (ترتيب إنشاء النماذج وهكذا N) هو أنه يمكنك استخدامه عدة مرات عندما يحتاج تطبيقك إلى بعض الوقت للتفكير.

قم بإنشاء شاشة البداية في DPR أولا، لكن لا تستخدم application.createform. طريقة لذلك. هنا بعض الرمز البسيط:

begin
  Application.Initialize;
  SplashForm := TSplashForm.Create(nil);
  try
    SplashForm.FormStyle := fsStayOnTop;
    SplashForm.Show;
    Application.ProcessMessages;
    Application.CreateForm(TForm14, Form14);
    // Other Form Creation here . . . .
    Application.Run;
  finally
    if assigned(SplashForm) then
      SplashForm.Release;
  end;
end.

ثم ضع التعليمات البرمجية التالية في معالج الأحداث المعرض (أو الأحدث - عند الانتهاء من التهيئة الخاصة بك) لنصفك (في هذه الحالة Form14):

SplashForm.Close;
SplashForm.Release;
SplashForm := nil;

(يمكنك استدعاء الإصدار في نموذج بدلا من الحرة، وقمت بتعيينها على Nil حتى لا يقوم DRP بالاتصال بالإصدار مرة أخرى. يتم الإصدار الموجود في DRP فقط في حالة فشلك Mainform في إنشاء.)

منذ نموذج البداية الخاص بك هو FormStyle: = fsstayontop لا ينبغي أن يكون مشكلة أنه لا يحصل على رسائل ترسم عند كتل الرسائل الرئيسية الخاصة بك. ثم عند إلغاء الخيط الرئيسي لإرسال رسالة لتحديثها (لتغيير شريط التقدم، وما إلى ذلك) على الرغم من أنني أتفق مع GameCat قد ترغب في الاتصال بائعي مكونات الطرف الثالث الخاص بك والحصول عليها للتوقف عن حظر الخيط الرئيسي عليك.

بدلا من ذلك، يمكنك إنشاء مكونات الطرف الثالث الخاص بك في مؤشر ترابط منفصل (شريطة ألا تكون مرئيا، لأن ذلك سيكون أكثر صعوبة قليلا.)

هذا سيعمل مع application.mainformontaskbar. تعيين إلى True كذلك.

أقوم بإنشاء دفقة في رمز بدء التشغيل، مع مجموعة أعلى دائما، ثم استخدم frmsplash.update في الأماكن المناسبة للتأكد من أنه مرئي ومحدث. النموذج الرئيسي يخلق هو مكان واحد للاتصال به.

المشكلة هي أن Delphi 2007 يفترض أن النموذج الأول هو الآن النموذج الرئيسي، وليس هناك طريقة لاستبدال النموذج الرئيسي في التعليمات البرمجية الأساسية، وبالتالي فإن البقع ليست جيدة أكثر من ذلك. ربما الحل القديم Visual Basic الخاص بوجود تطبيق Splash Fast Little الذي يدير التطبيق الرئيسي قد يكون في الواقع أفضل!

لم يتم حل مشكلة مؤشر ترابط منع الخيط الرئيسي عن طريق تشغيل شاشة البداية في مؤشر ترابط منفصل لأنه سيحتاج إلى الخيط الرئيسي لتحديثات الشاشة.

لا تتغير شاشة البداية، هذه ليست مشكلة.

ربما يجب عليك الاتصال بائع مكونات الطرف الثالث الخاص بك، لأن كتلة طويلة مثل هذه مشكلة حقيقية.

حصلت جيم ماكيث على فكرة رائعة هناك، لكنه لا يعالج شيئا واحدا قد يكون أو لا يكون مشكلة. تتحدث عن المكونات التي تستغرق وقتا طويلا للتهيئة. من ذلك، هل تقصد التهيئة القسم، أو شيء ما يحدث في وقت لاحق، كما هو الحال في حين يتم إنشاء نماذجك؟ لأن جميع أقسام التهيئة تعمل قبل تشغيل أي رمز في DPR. هذا الجزء الذي يستغرق وقتا طويلا، سيتعين عليك القيام ببعض الأشياء الصعبة للحصول على شاشة البداية الخاصة بك لإظهارها أمام كل ذلك:

ضع وحدة النموذج بالقرب من الجزء العلوي من .DPR كما يمكنك. (ولكن ليس قبل الأشياء التي تحتاج إلى الذهاب أولا، مثل fastmm). ضع التعليمات البرمجية لإظهار شاشة البداية في قسم التهيئة في تلك الوحدة. وتأكد من عدم وجود أي وحدات مع فترات التهيئة الطويلة التي تستخدمها شاشة البداية الخاصة بك (أو تلك التي تستخدمها استخدامها ... أو في أي مكان في شجرة التبعية.) ثم نأمل أن يعمل.

إذا لم تبدأ مشاكل التباطؤ إلا بعد انتهاء مكدس التهيئة الأولية، على الرغم من ذلك، فانتقل مع ما قاله جيم.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top