دلفي باسكال المشكلة عندما WMDeviceChange المكالمات وظيفة وظائف أخرى/الإجراءات

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

سؤال

حل

أنا باستخدام دلفي 2009.البرنامج يستمع usb محركات الأقراص متصلا وإزالة.لقد استخدمت مشابهة جدا مدونة في 10 تطبيقات على مدى العام الماضي.لطالما عملت تماما.عندما هاجر اضطررت إلى التخلي عن استخدام thddinfo للحصول على نموذج محرك الأقراص.هذا وقد تم استبدال باستخدام WMI.WMI استعلام يتطلب القرص الفعلي وأنا يحدث بالفعل وظيفة في التطبيق يفعل ذلك.

وأنا اختبار أضع هذا في زر وركض ذلك بنجاح يحدد psp هو محرك الأقراص الفعلي 4 و إرجاع نموذج (كل فحص في المصحح و في مثال آخر باستخدام تظهر الرسالة):

function IsPSP(Drive: String):Boolean;
var
Model: String;
DriveNum: Byte;
begin
  Result := False;
  Delete(Drive, 2, MaxInt);
  DriveNum := GetPhysicalDiskNumber(Drive[1]);
  Model := (MagWmiGetDiskModel(DriveNum));
  if Pos('PSP',Model) > 0 then Result := True;
end;

procedure TfrmMain.Button1Click(Sender: TObject);
var DriveNum: Byte;
begin
  IsPSP('I');
end;

أنها تعمل تماما حتى لا تسمح WMDeviceChange أن إيف تم استخدام لمدة سنة استدعاء getphysicaldisknumber و wmi جملة الاستعلام.جربت لهم من قبل أنفسهم هم كل مشكلة.GetPhysicalDiskNumber يتجمد سيء عندما تقوم CloseHandle على القرص المنطقي ولكن لا عودة عدد في نهاية المطاف.WMI يفشل الاستعلام مع أي خطأ فقط إرجاع " المصحح نقطة في wbemscripting_tlb حيث الاتصال فقط لم يحدث أبدا.نضع في اعتبارنا الشيء الوحيد الذي يكون تغير في السنة ما انا اتصل للحصول على نموذج كنت استخدام استدعاء api و الآن ايم باستخدام شيء آخر.

وفيما يلي بقية رمز تشارك في هذا الوقت بلا ispsp التي يتم عرضها أعلاه:

procedure TfrmMain.WMDeviceChange(var Msg: TMessage);
var Drive: String;
begin
  case Msg.wParam of
    DBT_DeviceArrival: if PDevBroadcastHdr(Msg.lParam)^.dbcd_devicetype = DBT_DevTyp_Volume then
      begin
        Drive := GetDrive(PDevBroadcastVolume(Msg.lParam)) + '\';
        OnDeviceInsert(Drive);
      end;
    DBT_DeviceRemoveComplete: if PDevBroadcastHdr(Msg.lParam)^.dbcd_devicetype = DBT_DevTyp_Volume then
      begin
        Drive := GetDrive(PDevBroadcastVolume(Msg.lParam)) + '\';
        OnDeviceRemove(Drive);
      end;
  end;
end;

Procedure TfrmMain.OnDeviceInsert(Drive: String);
var PreviousIndex: Integer;
begin
  if (getdrivetype(Pchar(Drive))=DRIVE_REMOVABLE) then
  begin
    PreviousIndex := cbxDriveList.Items.IndexOf(cbxDriveList.Text);
    cbxDriveList.Items.Append(Drive);
    if PreviousIndex = -1 then //If there was no drive to begin with then set index to 0
    begin
      PreviousIndex := 0;
      cbxDriveList.ItemIndex := 0;
    end;
    if isPSP(Drive) then
    begin
      if MessageDlg('A PSP was detect @ ' + Drive + #10#13 + 'Would you like to select this drive?',mtWarning,[mbYes,mbNo], 0) = mrYes then
      cbxDriveList.ItemIndex := cbxDriveList.Items.IndexOf(Drive)
      else cbxDriveList.ItemIndex := PreviousIndex;
    end
    else if MessageDlg('USB Drive ' + Drive + ' Detected' + #10#13 + 'Is this your target drive?',mtWarning,[mbYes,mbNo], 0) = mrYes then
        cbxDriveList.ItemIndex := cbxDriveList.Items.IndexOf(Drive)
    else cbxDriveList.ItemIndex := PreviousIndex;
  end;
end;

Procedure TfrmMain.OnDeviceRemove(Drive: String);
begin
  if not (getdrivetype(Pchar(Drive)) = DRIVE_CDROM) then
  begin
    if cbxDriveList.Text = (Drive) then ShowMessage('The selected drive (' + Drive + ') has been removed');
    cbxDriveList.Items.Delete(cbxDriveList.Items.IndexOf(Drive));
    if cbxDriveList.Text = '' then cbxDriveList.ItemIndex := 0;
    if Drive = PSPDrive then //Check Detect PSP and remove reference if its been removed
    begin
      PSPDrive := '';
    end;
  end;
end;

روب قد قال شيئا أدناه حول لست استدعاء الموروث معالج الرسالة, لقد قرأت الوثيقة أرى زوجين من الأشياء التي أستطيع العودة...ولكن أنا لست متأكدا من أنني أفهم ولكن سوف ننظر في الأمر.أنا لست جيدة جدا باسكال مبرمج ولكن إيف تم تعلم الكثير.الانتقال إلى 2009 كان بعض البقع الخام أيضا.

USB محرك الكشف عن كل شيء يعمل تماما.إذا كنت إزالة شيئين من هو psp المستخدم استقبال على الفور مع wis هذا ما يضيف I:\ إلى القائمة.فقط من الأشياء التي تغيرت في التطبيق أن تفشل عندما دعا من قبل wmdevicechange و كما قلت من قبل أنها تعمل من تلقاء نفسها.

تحرير - حل

حسنا حسنا im باستخدام الموقت كما اقترح و يبدو أن المشكلة يمكن حلها.ملاحظة واحدة هي أنه عندما دعا من قبل جهاز ضبط الوقت في وقت قريب جدا بعد wmdevicechange الحصول على القرص الفعلي يبدو أنه لا يزال بطيئا.أنا يعزو هذا الجهاز لا تزال تعلق على النظام.

على أن ملاحظة im باستخدام P2 450 العادي.أنا مدمن مخدرات PSP و التطبيق إلى 1.8 Ghz ثنائي النواة الكمبيوتر المحمول و برنامج الكشف عن psp و إخطار المستخدم سريع جدا.وبالتالي فإن التطبيق لن تجميد إلا على بطيئة جدا جدا الكمبيوتر على هذا بطيئة onw فقط لمدة ثوان و لا تؤثر على عمل البرنامج على الرغم من ليس بارد جدا.ولكن أشعر أن كل أجهزة الكمبيوتر الحديثة سيتم تشغيل الكشف السريع خاصة لأنها يمكن أن نعلق الجهاز الكثير أسرع.

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

المحلول

فمن الممكن أن المعلومات التي كنت الاستعلام يصبح متاح فقط بعد على WMDeviceChange رسالة معالج يعمل.إذا نفس الكود يعمل عندما دعا من زر جرب هذا:

  1. ريفاكتور الخاص بك WMDeviceChange رمز معالج في واحدة أو أكثر من طرق منفصلة.
  2. في WMDeviceChange معالج تنشيط precreated الموقت يكون عليه النار ثانية واحدة في وقت لاحق ، أو شيء من هذا القبيل.
  3. وندعو السابق WMDeviceChange رمز معالج من توقيت رمز معالج.

نصائح أخرى

وكنت لم المشار إليها ما "البيان 1" هو في التعليمات البرمجية.

ولدي بعض الملاحظات حول أجزاء من القانون، التي قد تكون أو لا تكون ذات صلة لمشكلة كنت تواجهها.

أولا، يجب تعيين قيمة DriveNum في IsPSP، ولكنك لا يستخدمونه. المترجم يجب أن تصدر إشارة عن ذلك. لا تتجاهل النصائح والتحذيرات. يمكنك أيضا تمرير الرقم السحري 4 إلى MagWmiGetDiskModel. كان من المفترض أن يتم DriveNum بدلا من ذلك؟

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

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

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