Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«ΠŸΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Windows APIΒ». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 17

Автор А. Π›Π΅Π³Π°Π»ΠΎΠ²

 // Draw a divider using XOR mode

 UpdateCanvas canvas(_hwndParent);

 ModeSetter mode(canvas, R2_NOTXORPEN);

 canvas.Line (_dragX, 0, _dragX, _cy - 1);

 }

Когда лСвая ΠΊΠ½ΠΎΠΏΠΊΠ° ΠΌΡ‹ΡˆΠΈ Π½Π°ΠΆΠ°Ρ‚Π° Π½Π°Π΄ клиСнтской ΠΎΠ±Π»Π°ΡΡ‚ΡŒΡŽ расщСпитСля, ΠΌΡ‹ выполняСм ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ Π·Π°Π΄Π°Ρ‡ΠΈ. Π‘Π½Π°Ρ‡Π°Π»Π° ΠΌΡ‹ фиксируСм ΠΌΡ‹ΡˆΡŒ. ΠŸΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈ, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ Π±ΡƒΠ΄Π΅Ρ‚, ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π°ΡŽΡ‚ курсор ΠΌΡ‹ΡˆΠΈ Π²Π½Π΅ полоски расщСпитСля. Ѐиксация ΠΌΡ‹ΡˆΠΈ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ всС Π΅Π΅ сообщСния Π±ΡƒΠ΄ΡƒΡ‚ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½Ρ‹ ΠΊ Π½Π°ΠΌ, Π΄Π°ΠΆΠ΅ Π² Ρ‚ΠΎΠΌ случаС, ΠΊΠΎΠ³Π΄Π° курсор ΠΌΡ‹ΡˆΠΈ Π±ΡƒΠ΄Π΅Ρ‚ Π±Π»ΡƒΠΆΠ΄Π°Ρ‚ΡŒ ΠΏΠΎ всСму экрану.

Π—Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅ΠΌ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ сплиттСра Π² ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ ΠΎΠΊΠ½Π°. ΠœΡ‹ Π΄Π΅Π»Π°Π΅ΠΌ это ΠΊΠΎΠ½Π²Π΅Ρ€Ρ‚Π°Ρ†ΠΈΠ΅ΠΉ Π½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹Ρ… ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ родитСля ΠΊ экранным ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Π°ΠΌ ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Π°ΠΌ дисплСя ΠΈ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ Π½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ нашСго расщСпитСля Ρ‚Π°ΠΊΠΆΠ΅ ΠΊ экранным ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Π°ΠΌ дисплСя. Π Π°Π·Π½ΠΈΡ†Π° Π΄Π°Π΅Ρ‚ Π½Π°ΠΌ Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅ ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ клиСнтской области родитСля. ΠœΡ‹ Π΄Π΅Π»Π°Π΅ΠΌ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ арифмСтичСскиС вычислСния, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π°ΠΉΡ‚ΠΈ ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρƒ x Ρ†Π΅Π½Ρ‚Ρ€Π° расщСпитСля, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ это - Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π±ΡƒΠ΄Π΅ΠΌ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π°Ρ‚ΡŒ.

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŽ, ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π°ΡŽΡ‰Π΅ΠΌΡƒ сплиттСр, ΠΎΠ±Ρ€Π°Ρ‚Π½ΡƒΡŽ связь, ΠΌΡ‹ рисуСм ΠΎΠ΄ΠΈΠ½ΠΎΡ‡Π½ΡƒΡŽ Π²Π΅Ρ€Ρ‚ΠΈΠΊΠ°Π»ΡŒΠ½ΡƒΡŽ линию, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Π±ΡƒΠ΄Π΅ΠΌ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π°Ρ‚ΡŒ ΠΏΠΎΠΏΠ΅Ρ€Π΅ΠΊ клиСнтской области Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ ΠΎΠΊΠ½Π°. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Π΄Π²Π΅ Π²Π°ΠΆΠ½Ρ‹Ρ… Π΄Π΅Ρ‚Π°Π»ΠΈ. Π₯олст, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΡ‹ создаСм, связан с Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»Π΅ΠΌ β€” ΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ дСскриптор ΠΎΠΊΠ½Π° родитСля. Π Π΅ΠΆΠΈΠΌ пСрСрисовки ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Π»ΠΎΠ³ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ xor (ΠΈΡΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰Π΅Π΅ ΠΈΠ»ΠΈ). Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ пиксСлы, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΡ‹ рисуСм, β€” ΠΊΠΎΠ½Π²Π΅Ρ€Ρ‚ΠΈΡ€ΡƒΡŽΡ‚ΡΡ с ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹ΠΌΠΈ пиксСлами с использованиСм xor. ЛогичСская опСрация xor ΠΈΠΌΠ΅Π΅Ρ‚ ΠΏΠΎΠ»Π΅Π·Π½ΡƒΡŽ ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΡŒ. Если Π’Ρ‹ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚Π΅ Π΅Π΅ Π΄Π²Π°ΠΆΠ΄Ρ‹, Π’Ρ‹ восстановитС ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π». Π­Ρ‚ΠΎΡ‚ самый старый ΠΏΡ€ΠΈΠ΅ΠΌ Π² ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π½ΠΎΠΉ Π³Ρ€Π°Ρ„ΠΈΠΊΠ΅ β€” ΠΌΠ΅Ρ‚ΠΎΠ΄ простой Π°Π½ΠΈΠΌΠ°Ρ†ΠΈΠΈ. Π’Ρ‹ рисуСтС Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ xor Ρ€Π΅ΠΆΠΈΠΌ ΠΈ стираСтС простым рисованиСм Π΅Π³ΠΎ ΠΆΠ΅ снова Π² xor Ρ€Π΅ΠΆΠΈΠΌΠ΅. Π˜Ρ‚Π°ΠΊ, рассмотрим ΠΊΠΎΠ΄ пСрСмСщСния, прСдставлСнный Π½ΠΈΠΆΠ΅.

void SplitController::LButtonDrag(POINTS pt) {

 if (_hwnd.HasCapture()) {

  // Erase previous divider and draw new one

  UpdateCanvas canvas(_hwndParent);

  ModeSetter mode(canvas, R2_NOTXORPEN);

  canvas.Line(_dragX, 0, _dragX, _cy - 1);

  _dragX = _dragStart + pt.x;

  canvas.Line(_dragX, 0, _dragX, _cy - 1);

 }

}

ΠœΡ‹ рисуСм Π²Π΅Ρ€Ρ‚ΠΈΠΊΠ°Π»ΡŒΠ½ΡƒΡŽ линию Π² xor Ρ€Π΅ΠΆΠΈΠΌΠ΅, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΡƒΡŽ ΡΠΎΡ…Ρ€Π°Π½Π΅Π½Π½ΡƒΡŽ ΠΏΠΎΠ·ΠΈΡ†ΠΈΡŽ. Π’Π°ΠΊ ΠΊΠ°ΠΊ это рисованиС происходит Π²ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΉ Ρ€Π°Π·, ΠΌΡ‹ рисуСм эту линию Π² Ρ‚ΠΎΠΌ ΠΆΠ΅ самом мСстС ΠΈ, Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅, Π±ΡƒΠ΄ΡƒΡ‚ восстановлСны ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹Π΅ пиксСлы ΠΈΠ·-ΠΏΠΎΠ΄ этой Π»ΠΈΠ½ΠΈΠΈ. Π—Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ рисуСм Π½ΠΎΠ²ΡƒΡŽ линию Π² Π½ΠΎΠ²ΠΎΠΉ ΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ, Ρ‚Π°ΠΊΠΆΠ΅ Π² xor Ρ€Π΅ΠΆΠΈΠΌΠ΅. ΠœΡ‹ Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ эту ΠΏΠΎΠ·ΠΈΡ†ΠΈΡŽ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Ρ€Π°Π·, ΠΊΠΎΠ³Π΄Π° вызовСтся LButtonDrag, ΠΌΡ‹ ΠΌΠΎΠ³Π»ΠΈ ΡΡ‚Π΅Ρ€Π΅Ρ‚ΡŒ Π΅Π΅ Ρ‚Π°ΠΊΠΆΠ΅. И Ρ‚Π°ΠΊ Π΄Π°Π»Π΅Π΅, ΠΏΠΎΠΊΠ° ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ Π½Π΅ отпустит ΠΊΠ½ΠΎΠΏΠΊΡƒ ΠΌΡ‹ΡˆΠΈ.

void SplitController::LButtonUp(POINTS pt) {

 // Calling ReleaseCapture will send us the WM_CAPTURECHANGED

 _hwnd.ReleaseMouse();

 _hwndParent.SendMessage(MSG_MOVESPLITTER, _dragStart + pt.x);

}

Π’ этой Ρ‚ΠΎΡ‡ΠΊΠ΅ ΠΌΡ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡΡ‚Π΅Ρ€Π΅Ρ‚ΡŒ Π²Π΅Ρ€Ρ‚ΠΈΠΊΠ°Π»ΡŒΠ½ΡƒΡŽ строку Π² послСдний Ρ€Π°Π·. Однако, ΠΌΡ‹ Π½Π΅ Π΄Π΅Π»Π°Π΅ΠΌ это нСпосрСдствСнно β€” ΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ здСсь нСбольшой ΠΏΡ€ΠΈΠ΅ΠΌ. ΠœΡ‹ ΠΏΡ€Π΅ΠΊΡ€Π°Ρ‰Π°Π΅ΠΌ сбор Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΡ‹ΡˆΠΈ. Как ΠΏΠΎΠ±ΠΎΡ‡Π½Ρ‹ΠΉ эффСкт, Windows посылаСт Π½Π°ΠΌ сообщСниС WM_CAPTURECHANGED. Π’ΠΎ врСмя ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ этого сообщСния, ΠΌΡ‹ фактичСски ΠΈ стираСм Π²Π΅Ρ€Ρ‚ΠΈΠΊΠ°Π»ΡŒΠ½ΡƒΡŽ строку.

void SplitController::CaptureChanged() {

 // We are losing capture

 // End drag selection -- for whatever reason

 // Erase previous divider

 UpdateCanvas canvas(_hwndParent);

 ModeSetter mode(canvas, R2_NOTXORPEN);

 canvas.Line(_dragX, 0, _dragX, _cy - 1);

}

ΠŸΠΎΡ‡Π΅ΠΌΡƒ ΠΌΡ‹ Π΄Π΅Π»Π°Π΅ΠΌ это Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ? ΠŸΠΎΡ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ Windows ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ нас, ΠΏΡ€Π΅ΠΊΡ€Π°Ρ‚ΠΈΡ‚ΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΡ‚ ΠΌΡ‹ΡˆΠΈ ΠΏΡ€Π΅ΠΆΠ΄Π΅, Ρ‡Π΅ΠΌ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ опустит Π΅Π΅ ΠΊΠ½ΠΎΠΏΠΊΡƒ. Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠ»ΡƒΡ‡ΠΈΡ‚ΡŒΡΡ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΊΠΎΠ³Π΄Π° Π΄Ρ€ΡƒΠ³ΠΎΠ΅ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π²Π½Π΅Π·Π°ΠΏΠ½ΠΎ Ρ€Π΅ΡˆΠ°Π΅Ρ‚ Ρ€Π°ΡΠΏΠ°Ρ…Π½ΡƒΡ‚ΡŒ Π΅Π³ΠΎ ΠΎΠΊΠ½ΠΎ, Π² Ρ‚ΠΎ врСмя ΠΊΠ°ΠΊ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ находится Π² процСссС пСрСмСщСния. Π’ этом случаС нашС ΠΎΠΊΠ½ΠΎ Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΎ Π±Ρ‹ сообщСниС ΠΎΠ± ΠΎΡ‚ΠΆΠ°Ρ‚ΠΈΠΈ ΠΊΠ½ΠΎΠΏΠΊΠΈ. Если Π±Ρ‹ ΠΌΡ‹ Π½Π΅ Π±Ρ‹Π»ΠΈ Ρ‚Π°ΠΊ ΡƒΠΌΠ½Ρ‹, ΠΌΡ‹ Π±Ρ‹ Π½Π΅ Π±Ρ‹Π»ΠΈ способны чисто ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π°Ρ‚ΡŒΡΡ. К ΡΡ‡Π°ΡΡ‚ΡŒΡŽ, ΠΏΠ΅Ρ€Π΅Π΄ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅ΠΌ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΡ‹ΡˆΠΈ, Windows сумССт ΠΏΠΎΡΠ»Π°Ρ‚ΡŒ Π½Π°ΠΌ сообщСниС WM_CAPTURECHANGED, ΠΈ ΠΌΡ‹ ΠΏΡ€ΠΈΠΌΠ΅ΠΌ Π΅Π³ΠΎ ΠΊ свСдСнию, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Π½Π°ΡˆΡƒ очистку.

ВСрнСмся снова ΠΊ LBUTTONUP β€” ΠΊΠΎΠ³Π΄Π° ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ Π·Π°ΠΊΠ°Π½Ρ‡ΠΈΠ²Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠ΅, ΠΌΡ‹ посылаСм Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŽ нашС ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠ΅ сообщСниС MSG_MOVESPLITTER, пСрСдавая Π΅ΠΌΡƒ Π½ΠΎΠ²ΡƒΡŽ ΠΏΠΎΠ·ΠΈΡ†ΠΈΡŽ Ρ†Π΅Π½Ρ‚Ρ€Π° полосы расщСпитСля, измСряСмой Π² ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Π°Ρ… клиСнтской области родитСля. Π’Ρ‹ ΡƒΠΆΠ΅ Π²ΠΈΠ΄Π΅Π»ΠΈ клиСнтский ΠΊΠΎΠ΄, Ρ€Π΅Π°Π³ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ Π½Π° это сообщСниС.

Π—Π΄Π΅ΡΡŒ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ клиСнтскоС сообщСниС.

// Reserved by Reliable Software Library

const UINT MSG_RS_LIBRARY = WM_USER + 0x4000;

// wParam = new position wrt parent's left edge

const UINT MSG_MOVESPLITTER = MSG_RS_LIBRARY + 1;

Π’ Π·Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ прСдставлСн Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ ΠΈΠ· ΠΎΡ‡Π΅Π½ΡŒ ΠΏΠΎΠ»Π΅Π·Π½ΠΎΠ³ΠΎ класса HWnd, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ инкапсулируСт ΠΌΠ½ΠΎΠ³ΠΈΠ΅ базисных Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ API Windows, ΠΈΠΌΠ΅ΡŽΡ‰ΠΈΠ΅ Π΄Π΅Π»ΠΎ с ΠΎΠΊΠ½Π°ΠΌΠΈ. Π’ частности, рассмотритС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ MoveDelayPaint ΠΈ ForceRepaint, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΡ‹ использовали Π² пСрСрисовкС полоски расщСпитСля.

class HWnd {

public:

 void Update() {

  ::UpdateWindow(_hwnd);

 }

 // Moving

 void Move(int x, int y, int width, int height) {

  ::MoveWindow(_hwnd, x, y, width, height, TRUE);

 }

 void MoveDelayPaint(int x, int y, int width, int height) {

  ::MoveWindow(_hwnd, x, y, width, height, FALSE);

 }

 // Repainting

 void Invalidate() {

  ::InvalidateRect(_hwnd, 0, TRUE);

 }

 void ForceRepaint() {

  Invalidate();

  Update();

 }

 private:

 HWND _hwnd;

};

Как ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ, Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π·Π°Π³Ρ€ΡƒΠ·ΠΈΡ‚ΡŒ ΠΏΠΎΠ»Π½Ρ‹ΠΉ исходный тСкст прилоТСния, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ использовалось Π² этом ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅.

Π”Π°Π»Π΅Π΅: Π‘Π»Π΅Π΄ΡƒΡŽΡ‰Π°Ρ ΠΎΠ±ΡƒΡ‡Π°ΡŽΡ‰Π°Ρ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° рассказываСт ΠΎ растрах.

Bitmaps

In this tutorial we'll learn how to load bitmaps from resources and from files, how to pass them around and blit them to the screen. We'll also see how to create and use an empty bitmap as a canvas, draw a picture on it and then blit it to the screen. Finally, we'll combine these techniques to write a simple program that uses double-buffering and timer messages to show a simple animation involving sprites.

First of all, in most cases Windows provides storage for bitmaps and takes care of the formatting of bits. The programmer gets access to the bitmap through a handle, whose type is HBITMAP. (Remember to set the STRICT flag when compiling Windows programs, to make sure HBITMAP is a distinct type, rather than just a pointer to void.)

Since a bitmap is a resource (in the Resource Management sense), the first step is to encapsulate it in a β€œstrong pointer” type of interface. Notice the transfer semantics of the constructor and the overloaded assignment operator, characteristic of a resource that can have only one owner at a time.

We instruct Windows to release the resources allocated to the bitmap by calling DeleteObject.

class Bitmap {

public:

 Bitmap() : _hBitmap (0) {}

 // Transfer semantics

 Bitmap(Bitmap& bmp) : _hBitmap(bmp.Release()) {}

 void operator=(Bitmap& bmp) {

  if (bmp._hBitmap != _hBitmap) {

   Free();

  _hBitmap = bmp.Release();

  }

 }

 HBITMAP Release() {

 HBITMAP h = _hBitmap;

  _hBitmap = 0;

  return h;

 }

 ~Bitmap() {

  Free();

 }

 // implicit conversion for use with Windows API

 operator HBITMAP() {

  return _hBitmap;

 }

protected:

 Bitmap(HBITMAP hBitmap) : _hBitmap(hBitmap) {}

 void Free() {

  if (_hBitmap) ::DeleteObject(_hBitmap);

 }

 HBITMAP _hBitmap;

};

Now that the management issues are out of the way, we can concentrate on loading bitmaps. The simplest way to include a bitmap in your program is to add it to the resource file. In the resource editor of your development environment you can create new bitmaps or import them from external files. You can either give them names (strings) or numerical ids. When you want to access such a bitmap in your program you have to load it from the resources. Here are two methods that do just that. You have to give them a handle to the program instance.

void Bitmap::Load(HINSTANCE hInst, char const * resName) {

 Free();

 _hBitmap = (HBITMAP)::LoadImage(hInst, resName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);

 if (_hBitmap == 0) throw WinException("Cannot load bitmap from resources", resName);

}


void Bitmap::Load(HINSTANCE hInst, int id) {

 Free();

 _hBitmap = (HBITMAP)::LoadImage(hInst, MAKEINTRESOURCE(id), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);

 if (_hBitmap == 0) throw WinException("Cannot load bitmap from resources");

}

Loading a bitmap directly from a file is also very simple and can be done using the same API, LoadImage. Remember, it will only work if the file is a Windows (or OS/2) bitmap β€” such files usually have the extension .bmp. There is no simple way of loading other types of graphics files, .gif, .jpg, .png, etc. You have to know their binary layout and decode them explicitly (there are other web sites that have this information).

void Bitmap::Load(char* path) {

 Free();

 _hBitmap = (HBITMAP)::LoadImage(0, path, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

 if(_hBitmap == 0) throw WinException("Cannot load bitmap from file", path);

}

Once you got hold of a bitmap, you may want to enquire about its dimensions. Here's how you do it.

void Bitmap::GetSize(int& width, int& height) {

 BITMAP bm;

 ::GetObject(_hBitmap, sizeof(bm), &bm);

 width = bm.bmWidth;

 height = bm.bmHeight;

}

Finally, you might want to create an empty bitmap and fill it with your own drawings programmatically. You have to specify the dimensions of the bitmap and you have to provide a device context (Canvas) for which the bitmap is targeted. Windows will create a different type of bitmap when your target is a monochrome monitor or printer, and different when it's a graphics card set to True Color. Windows will create a bitmap that is compatible with the target device.