سؤال

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

حاول

SendMessage( gridX.Handle, WM_VSCROLL, SB_LINEDOWN, 0 );

أيضا

procedure TForm1.GridXCustomWndProc( var Msg: TMessage );
begin
Msg.Result := CallWindowProc( POldWndProc, gridX.Handle, Msg.Msg, Msg.wParam, Msg.lParam );

   if ( Msg.Msg = WM_VSCROLL ) then 
   begin
      gridY.SetActiveRow( gridX.GetActiveRow );
      gridY.Perform( Msg.Msg, Msg.wParam, Msg.lParam );
      SetScrollPos( gridY.Handle, SB_VERT, HIWORD( Msg.wParam ), True );
   end;
end;

و

procedure TForm1.GridxCustomWndProc( var Msg: TMessage );
begin
   if ( Msg.Msg = WM_VSCROLL ) then 
   begin
      gridY.SetActiveRow( gridX.GetActiveRow );
      gridY.Perform( Msg.Msg, Msg.wParam, Msg.lParam );
      SetScrollPos( gridY.Handle, SB_VERT, HIWORD( Msg.wParam ), True );
   end;
   inherited WndProc( Msg );
end;

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

تحديث:الحل

  private
    [...]
    GridXWndProc, GridXSaveWndProc: Pointer;
    GridYWndProc, GridYSaveWndProc: Pointer;
    procedure GridXCustomWndProc( var Msg: TMessage );
    procedure GridYCustomWndProc( var Msg: TMessage );

procedure TForm1.FormCreate(Sender: TObject);
begin
  GridXWndProc := classes.MakeObjectInstance( GridXCustomWndProc );
  GridXSaveWndProc := Pointer( GetWindowLong( GridX.Handle, GWL_WNDPROC ) );
  SetWindowLong( GridX.Handle, GWL_WNDPROC, LongInt( GridXWndProc ) );

  GridYWndProc := classes.MakeObjectInstance( GridYCustomWndProc );
  GridYSaveWndProc := Pointer( GetWindowLong( GridY.Handle, GWL_WNDPROC ) );
  SetWindowLong( GridY.Handle, GWL_WNDPROC, LongInt( GridYWndProc ) );
end;

procedure TForm1.GridXCustomWndProc( var Msg: TMessage );
begin
   Msg.Result := CallWindowProc( GridXSaveWndProc, GridX.Handle, Msg.Msg, Msg.WParam, Msg.LParam );
   case Msg.Msg of
      WM_KEYDOWN:
      begin
         case TWMKey( Msg ).CharCode of VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT:
            GridY.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
         end;
      end;
      WM_VSCROLL:
         GridY.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
      WM_HSCROLL:
         GridY.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
      WM_MOUSEWHEEL:
      begin
         ActiveControl := GridY;
         GridY.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
      end;
      WM_DESTROY:
      begin
         SetWindowLong( GridX.Handle, GWL_WNDPROC, Longint( GridXSaveWndProc ) );
         Classes.FreeObjectInstance( GridXWndProc );
      end;
  end;
end;

procedure TForm1.GridXMouseDown( Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer );
begin
   GridY.SetActiveRow( GridX.GetActiveRow );
end;

procedure TForm1.GridYCustomWndProc( var Msg: TMessage );
begin
   Msg.Result := CallWindowProc( GridYSaveWndProc, GridY.Handle, Msg.Msg, Msg.WParam, Msg.LParam );
   case Msg.Msg of
      WM_KEYDOWN:
      begin
         case TWMKey( Msg ).CharCode of VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT:
            GridX.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
         end;
      end;
      WM_VSCROLL:
         GridX.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
      WM_HSCROLL:
         GridX.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
      WM_MOUSEWHEEL:
      begin
         ActiveControl := GridX;
         GridX.Perform( Msg.Msg, Msg.WParam, Msg.LParam );
      end;
      WM_DESTROY:
      begin
         SetWindowLong( GridY.Handle, GWL_WNDPROC, Longint( GridYSaveWndProc ) );
         Classes.FreeObjectInstance( GridYWndProc );
      end;
   end;
end;

procedure TForm1.GridYMouseDown( Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer );
begin
   GridX.SetActiveRow( GridY.GetActiveRow );
end;

بفضل-سيرتاك أكيوز للحل.عند دمجها في تطبيق أشكال فكل باستخدام الشبكات ، وسوف ميميك بعضها البعض في التمرير ، وتسليط الضوء على السجل المحدد.

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

المحلول

من المحتمل أن تنفذ الرسالة تجاوز الرسالة لكل من الشبكات.Gridx Scrolls Gridy، والتي بدورها مخطوطات Gridx، والتي بدورها ... لذلك.يمكنك حماية رمز التمرير السطحي عن طريق تحيط الكتلة بالأعلام.

giveacodicetagpre.

رمز similiar للشبكة.راجع للشغل، أنت لا تحتاج إلى مجموعات المجموعات.


تحرير:

giveacodicetagpre.

نصائح أخرى

حصلت على حل فعالا جزئيا، لكنه يعمل الآن (على الأقل بالنسبة إلى TMEMO) ...

أعني جزئيا، لأنه يستمع فقط للتغييرات على TMEMO واحد ولكن ليس من ناحية أخرى ...

أعني العمل الكامل لأنه لا يعتمد على ما يتم ...

هو بسيط تماما مثل وضع نفس قيمة التمرير الأفقي على مذكرة واحدة كما هو من ناحية أخرى ...

لا يتعلق الأمر بالرسائل، ولكن منذ أن كنت أحاول الحصول على حل عامل من خلال رسائل المحاصرة WM_HSCROLL، إلخ ... تركت الكود لأنه يعمل ... سأحاول تحسينه لاحقا ... مثال على محاصرة فقط WM_PAINT، أو بطرق أخرى ... ولكن الآن، أضعها كما أن لدي منذ ذلك الحين لأنها تعمل ... ولم أجد أي مكان آخر أفضل ...

هنا هو الرمز الذي يعمل:

giveacodicetagpre.

يعمل طوال جميع الطرق لجعل التمرير للتغيير ...

ملاحظات:

  • أعلم أنه من الرهيب أن يحبس جميع الرسائل، ولكن على الأقل يعمل ...
  • هذا هو أول محاولة لنجاحي لأول مرة في TMEMOS مع Synced شريط التمرير الأفقي ...
  • لذلك، إذا كان شخص ما يمكن أن يحسنه قليلا (وليس فخ جميع الرسائل) من فضلك افعلها ونشرها.
  • يجعل فقط memo1 ليكون في مزامنة أفقية مع شريط memo2، ولكن ليس MEMO2 لتكون متزامنة مع memo1
  • مفاتيح الصحافة لأعلى، أسفل، اليسار، اليمين، الماوس، إلخ ... كل ما عليك تريد ولكن على memo2 لرؤيتها في العمل

سأحاول تحسينه بواسطة: عند القيام بشيء ما على MEMO2، لا يزال التمرير Memo1 في مزامنة ...

أعتقد أنه يمكن أن يعمل لأي تحكم بأي شيء يحتوي على شريط تمرير، وليس فقط TMEMO ...

كما قلت ...

هنا هو الحل الأفضل (وليس النهائي) من حيث الكفاءة، رمز نظيف و Bi-directional ... تغيير على أي واحد يؤثر على الآخر ...

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

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

الجزء الأول هو فقط إضافة أشياء إلى فئة TMEMO، فهي مجرد إنشاء فئة مشتقة جديدة ولكن مع نفس اسم الفصل، ولكن فقط للوحدة داخل المعلنة.

أضف هذا إلى قسم الواجهة، قبل إعلان TFORM الخاص بك، لذلك سوف يرى TFORM الخاص بك فئة TMEMO الجديدة هذه بدلا من One العادي:

giveacodicetagpre.

الجزء التالي هو تطبيق الإعلانات السابقة لدرجة TMEMO الجديدة.

أضف هذا إلى قسم التنفيذ في أي مكان تقوم به Preffer:

giveacodicetagpre.

الآن الجزء الأخير، أخبر كل TMEMO ما هي المذكرة الأخرى التي يجب أن تكون متزامنة.

على قسم التنفيذ الخاص بك، لإنشاء حدث Form1 إضافة شيء مثل هذا:

giveacodicetagpre.

تذكرنا أننا أضفنا عضو SyncMemo إلى فئة TMEMO الجديدة الخاصة، كان هناك فقط لهذا الغرض، أخبر بعضنا البعض ما هو واحد الآخر.

الآن تكوين صغير لكل من TMEMO JSUT للسماح لهذا العمل تماما:

  • دع كلا من أشرطة التمرير TMEMO مرئية
  • دع WallWrap False على كلا TMEMO
  • ضع الكثير من النص (نفسه لكل من) وخطوط طويلة والكثير من الخطوط

قم بتشغيله ومعرفة كيفية مزامنة كل من أشرطة التمرير الأفقي كلا دائما ...

  • إذا قمت بنقل سيارة سكرورة أفقية واحدة، فإن شريط التمرير الأفقي الآخر يتحرك ...
  • إذا ذهبت في النص إلى اليمين أو اليسار، أو نهاية الخط أو نهاية الخط، الخ ...، بغض النظر عن مكان سيلسارت على الآخر ... الأفقي التنقل النصي قيد التشغيل.

المشكلة لماذا هذا ليس إصدارا نهائيا هو أن:

  • أشرطة التمرير (واحد أفقي في حالتي) لا يمكن إخفاؤها ... نظرا لأنه إذا تم إخفاء المرء، عند الاتصال GetScrollprolpos، فإنه لا يؤدي ذلك إلى مزامنة.

إذا كان شخص ما يعرف كيفية محاكاة الخفية أو جعل GetScrollprolprolpors لعدم إرجاع الصفر، يرجى التعليق، الأمر الوحيد الذي أحتاجه لإصلاح النسخة النهائية.

ملاحظات:

  • من الواضح أن الشيء نفسه يمكن القيام به مع شريط التمرير العمودي ... فقط تغيير wm_hscroll إلى wm_vscroll و sb_horz إلى sb_vert
  • من الواضح أن الشيء نفسه يمكن القيام به كليهما في نفس الوقت ... فقط نسخ Syncmemo.perform Line مرتين وعلى واحد، دع WM_HSCROLL و SB_HORZ وعلى الآخر، دع WM_VSCROLL و SB_VART

هنا مثال على إجراء New_windowproc لمزامنة كل من سكر التمريض في نفس الوقت، ربما للأشخاص الكسولين، ربما للأشخاص مثل نسخ ولصق:

giveacodicetagpre.

آمل أن يحل شخص ما مشكلة شريط التمرير واحد مخفي و GetScrollprolprolprolprolpor returning صفر !!!

وجدت حلا ... أعرف أنه صعب للغاية ... ولكن على الأقل هو وظيفي بالكامل ...

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

الجزء الصعب:

  • ضع tpanel حيث يكون tmemo ووضع tmemo داخل tpanel
  • إخفاء حدود tpanel، ووضع الحدود كما 0، وجميع شطبة إلى bvnone / bknone
  • تكوين TMEMO محاذاة إلى Altop، وليس إلى Alclient، إلخ ...
  • التعامل مع tpanel.OnResize لجعل tmemo.height أكبر من tpanel.height بقدر ارتفاع شريط التمرير الأفقي (في الوقت الحالي، استخدم قيمة ثابتة من 20 بكسل، ولكن أود معرفة كيفية الحصول على القيمة الحقيقية) < / لى>

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

هنا هو الكود الكامل لأرشفة ذلك:

على قسم الواجهة، قبل إعلان TFORM الخاص بك، لذلك سوف يرى TFORM الخاص بك فئة TMEMO الجديدة هذه بدلا من One:

giveacodicetagpre.

على قسم التنفيذ في أي مكان تقوم به Preffer:

giveacodicetagpre.

أيضا على قسم التنفيذ في أي مكان تقوم به Preffer:

giveacodicetagpre.

ثاس هو الناس! أعلم أنه أمر صعب للغاية، ولكن يعمل بشكل كامل.

يرجى ملاحظة أنني قد تغيرت على new_windowproc ترتيب تقييم أو الشروط ... فقط لتحسين السرعة لجميع الرسائل الأخرى، لذلك تأخير أقل قدر ممكن من جميع الرسائل كل العلاج.

نأمل في وقت ما سأعرف كيفية استبدال مثل هذه العشرين من خلال الطابق الحقيقي (المحسوب أو القراء) TMEMO شريط التمرير الأفقي.

شكرا ل GetSystemMetrics و SM_CYHSCROLL, ، لكنها ليست كافية فقط...تحتاج فقط 3 بكسل أكثر...

لذلك أنا فقط استخدام: GetSystemMetrics(SM_CYHSCROLL)+3

ملاحظة:اثنين من هذه بكسل يمكن أن يكون بسبب وجود لوحة الأصل مع BevelWidth مع القيمة 1 ولكن لدي BevelInner و BevelOuter مع القيمة bvNone لذلك قد لا;ولكن بكسل اضافية أنا لا أعرف لماذا.

شكرا جزيلا.

إذا كنت تفضل, مجرد الانضمام إليها على وظيفة واحدة كبيرة, ولكن أعتقد أنه من الأفضل عدم مزجها.

ردا على "سيرتاك أكيوز" (آسف للقيام بذلك هنا ، ولكن أنا لا أعرف كيفية نشرها بجانب سؤالك):

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

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

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