4.ÆíÁý È÷½ºÅ丮

°¡.±×·ì Çì´õ

´ç±ÙÀÇ Ãë¼Ò, Àç½ÇÇà ±â´ÉÀº ¸Þ¸ð¸® ¿ë·®±îÁö ¹«ÇÑ ´Ü°èÀÇ ÆíÁý °úÁ¤À» ÀúÀåÇÒ ¼ö ÀÖ´Ù´Â ¸é¿¡¼­ »ó´çÈ÷ ¿ì¼öÇÑ ÆíÀÌ´Ù. ±×·±µ¥ Ãë¼Ò, Àç½ÇÇàÀ» ÇÒ ¶§ ÇÑ ´Ü°è¾¿¸¸ Ãë¼Ò, Àç½ÇÇàÇÒ ¼ö ÀÖÀ¸¹Ç·Î ÇÑÂü ÀÌÀüÀÇ ´Ü°è·Î µ¹¾Æ°¡°í ½ÍÀ¸¸é Ctrl+Z¸¦ °è¼Ó ´©¸£°í ÀÖ¾î¾ß ÇϹǷΠ´Ù¼Ò ºÒÆíÇÑ ¸éÀÌ ÀÖ´Ù. Áö±Ý±îÁö ÆíÁýÇß´ø °úÁ¤ÀÇ ¸ñ·ÏÀ» º¸¿©ÁÖ°í ÁöÁ¤ÇÑ ÁöÁ¡±îÁö ÇѲ¨¹ø¿¡ Ãë¼ÒÇÒ ¼ö ÀÖ´Ù¸é ´õ Æí¸®ÇÒ °ÍÀÌ´Ù. ºñÁÖ¾ó ½ºÆ©µð¿À¿Í ¿öµå¿¡ ÀÌ¹Ì ÀÌ ±â´ÉÀÌ ÀÛ¼ºµÇ¾î Àִµ¥ ÀÌ ±â´É°ú ¶È°°ÀÌ ¸¸µé¾î º¸ÀÚ.

 

ÀÌ ±â´ÉÀº ÇѲ¨¹ø¿¡ ÆíÁý µ¿ÀÛÀ» Ãë¼ÒÇÒ ¼ö ÀÖ´Ù´Â ¸é¿¡¼­ ½Ç¿ë¼ºÀÌ ÀÖÀ» »Ó¸¸ ¾Æ´Ï¶ó ÆíÁý ±â·ÏÀ» »ìÆì º¸´Â ¿ëµµ·Îµµ °¡Ä¡°¡ ÀÖ´Ù. ¸ñ·ÏÀ» ÆîÃÄ º¸¸é ¾î¶² µ¿ÀÛÀ» ¾î¶² ¼ø¼­´ë·Î ½ÇÇàÇß´ÂÁö¸¦ Àϸñ ¿ä¿¬ÇÏ°Ô ¾Ë ¼ö ÀÖ´Ù. »ðÀÔ, »èÁ¦, À̵¿ µîÀÇ µ¿ÀÛ¿¡ ´ëÇØ À̸§À» ºÙÀÌ°í »ðÀÔ, »èÁ¦ ´ë»ó±îÁöµµ Ç¥½ÃÇϸé ÆíÁý µ¿ÀÛÀ» ¿ä¾àÀûÀ¸·Î Ç¥ÇöÇÒ ¼ö ÀÖ´Ù.

±×·ì µ¿ÀÛÀº ¼¼ºÎÀûÀ¸·Î ¼ö¸¹Àº »ðÀÔ, »èÁ¦, À̵¿À¸·Î ÀÌ·ç¾îÁö´Âµ¥ ÇϳªÀÇ ÆíÁý µ¿ÀÛÀ» À§ÇÑ ±×·ìÀ̹ǷΠ¸ñ·Ï¿¡µµ Çϳª·Î ±â·ÏÇÏ´Â °ÍÀÌ ´õ ÁÁ´Ù. À̶§ ±×·ì µ¿ÀÛ¿¡ ´ëÇÑ ¼³¸íÀ» ¾î¶»°Ô Ç¥½ÃÇÒ °ÍÀΰ¡°¡ ¹®Á¦Àε¥ ±×·ì µ¿ÀÛ¿¡ ´ëÇؼ­µµ ¼³¸íÀ» ºÙÀÏ ¼ö ÀÖ¾î¾ß ÇÑ´Ù. ÇöÀç ÆíÁý ±×·ìÀº StartUndoGroup ÇÔ¼ö·Î ½ÃÀ۵Ǹç ƽ Ä«¿îÆ®¿Í ±×·ì ¼±µÎ ·¹ÄÚµåÀÇ ¹øÈ£¸¦ Á¶ÇÕÇÑ ±×·ì ID·Î ±×·ì¿¡ ¼ÓÇÑ ·¹Äڵ带 ±¸ºÐÇÒ »Ó º°µµÀÇ ¼³¸íÀº ÀÛ¼ºµÇÁö ¾Ê´Â´Ù. ±×·¡¼­ ±×·ì¿¡ ´ëÇÑ ¼³¸í ·¹Äڵ带 ÀÛ¼ºÇϱâ À§ÇØ UR_GROUPÀ̶ó´Â ·¹ÄÚµå ŸÀÔÀ» Ãß°¡ÇÑ´Ù.

 

enum { UR_NONE, UR_INSERT, UR_DELETE, UR_MOVE, UR_GROUP };

 

ÀÌ ·¹ÄÚµå´Â ½ÇÁ¦ ÆíÁý µ¿ÀÛÀ» ±â·ÏÇÏÁö´Â ¾ÊÁö¸¸ ±×·ì¿¡ ´ëÇÑ ¼³¸íÀ» ºÙÀÌ´Â ¿ëµµ·Î »ç¿ëµÈ´Ù. pos³ª len µîÀº »ç¿ëÇÏÁö ¾ÊÀ¸¸ç data¿¡ ¹®ÀÚ¿­ Æ÷¸ËÀ¸·Î ÆíÁý ±×·ì¿¡ ´ëÇÑ °£·«ÇÑ ¼³¸íÀ» ÀúÀåÇÒ °ÍÀÌ´Ù. ¿¹¸¦ µé¾î ºí·Ï µé¿©¾²±â µ¿ÀÛÀ» À§ÇÑ ÆíÁýÀ» ÇÑ´Ù¸é "ºí·Ï µé¿©¾²±â"¶ó´Â ¹®ÀÚ¿­À» °¡Áö´Â UR_GROUP ·¹Äڵ带 ¸ÕÀú ÀÛ¼ºÇÏ°í ÀÌ ·¹ÄÚµå µÚ¿¡ ÆíÁý µ¿ÀÛÀÇ ±×·ìÀÌ µû¶ó¿À´Â ½ÄÀÌ´Ù. ±×·ìÀ» ½ÃÀÛÇÏ´Â ÇÔ¼ö¸¦ ´ÙÀ½°ú °°ÀÌ ¼öÁ¤ÇÑ´Ù.

 

void CApiEdit::StartUndoGroup(int id, TCHAR *desc/*=NULL*/)

{

     // Ç×»ó »õ·Î¿î ·¹Äڵ忡¼­ ½ÃÀÛÇÏ¸ç º´ÇÕÇÏÁö ¾Ê´Â´Ù.

     if (CanRedo()) {

          ClearRedo();

     } else {

          if (pUR[nowur].action != UR_NONE) {

              NextRecord();

          }

     }

 

     // »õ ±×·ìÀÌ ½ÃÀ۵Ǹé UR_GROUP ·¹Äڵ带 ÀÛ¼ºÇÑ´Ù. Áßø ±×·ìÀº Á¦¿ÜÇÑ´Ù.

     if (URnest==0) {

          URtick=((nowur << 16) | (GetTickCount() & 0xffff));

 

          // ¼³¸íÀº desc¿¡ ÀÛ¼ºÇÏ°í ±×·ì id´Â pos¿¡ ±â·ÏÇÑ´Ù.

          if (desc) {

              AllocURData(nowur,lstrlen(desc)+1,0);

              lstrcpy(pUR[nowur].data,desc);

          } else {

              AllocURData(nowur,sizeof(int)*2,0);

              lstrcpy(pUR[nowur].data,"");

          }

          pUR[nowur].action=UR_GROUP;

          pUR[nowur].pos=id;

          pUR[nowur].tick=URtick;

     }

     URnest++;

}

 

±×·ì Çì´õ´Â Ç×»ó »õ·Î¿î ·¹Äڵ忡¼­ ½ÃÀÛÇÑ´Ù. Áï, ±×·ìÀº ±×·ì ÀÌÀüÀÇ ·¹ÄÚµå¿Í Á¶°ÇÀÌ ¸Â¾Æµµ º´ÇÕÇÏÁö ¾Ê´Â´Ù. 1.0ÀÇ º´ÇÕ ¾Ë°í¸®Áò¿¡ Ä¡¸íÀûÀÎ ¹®Á¦´Â ¾Æ´ÏÁö¸¸ ¾à°£ÀÇ ¹ö±×°¡ ÀÖ¾ú´Âµ¥ StartUndoGroupÀÌ »õ ·¹ÄÚµå ºÐÇÒÀ» ÇÏÁö ¾Ê±â ¶§¹®¿¡ ±×·ì°ú ¾È±×·ì ·¹Äڵ尡 º´ÇյǴ ¹®Á¦Á¡ÀÌ ÀÖ´Ù. ¿¹¸¦ µé¾î abcdef°¡ ÀԷµǾî ÀÖÀ» ¶§ dÀÚ¸®¿¡¼­ BS¼¼¹ø ´­·¯ abcÁö¿ì°í def¸¦ ºí·ÏÀ¸·Î ¼±ÅÃÇÑ ÈÄ ghi·Î ´ëüÇÏ¸é ´ÙÀ½°ú °°ÀÌ ±â·ÏµÈ´Ù.

 

¹®¼­

µ¿ÀÛ

·¹ÄÚµå

abcdef

abcÁö¿ò

abc »èÁ¦

def

def ¼±Åà ÈÄ ghi»ðÀÔ

abc »èÁ¦¿Í def »èÁ¦ º´ÇÕ

ghi »ðÀÔ

ghi

 

 

 

def »èÁ¦°¡ Á÷ÀüÀÇ abc »èÁ¦¿Í º´ÇÕµÇ¾î ¹ö¸®±â ¶§¹®¿¡ ghi »ðÀÔÀÌ ¼±Åà ´ëü ±×·ìÀ» ±¸¼ºÇÏÁö ¸øÇÏ´Â °ÍÀÌ´Ù. def »èÁ¦¿Í ghi »ðÀÔÀÌ ÇÑ µ¿ÀÛÀ̹ǷΠÀÌ µÑÀÌ ±×·ìÀÌ µÇ¾î¾ß Çϸç abc »èÁ¦¿Í def »èÁ¦´Â Á¶°ÇÀÌ ¸Â´õ¶óµµ ÇÑ ±×·ìÀÌ µÇ¾î¼­´Â ¾ÈµÈ´Ù. ÀÌ·± ¹®Á¦¸¦ ÇØ°áÇϱâ À§ÇØ ¾ÕÂÊ ·¹Äڵ忡 ÆíÁý µ¿ÀÛÀÌ ±â·ÏµÇ¾î ÀÖÀ¸¸é ¹«Á¶°Ç NextRecord·Î ´ÙÀ½ ·¹ÄÚµå·Î À̵¿Çß´Ù.

±×·ìÀÌ ½ÃÀ۵Ǹé UR_GROUP ±×·ì ·¹Äڵ带 ÀÛ¼ºÇÑ´Ù. Àμö·Î ±×·ìÀÇ µ¿ÀÛÀ» ¼³¸íÇÏ´Â Á¤¼öÇüÀÇ id¿Í Ãß°¡ ¼³¸í ¹®ÀÚ¿­À» Àü´Þ¹Þ¾Æ id´Â Ãë¼Ò ·¹ÄÚµåÀÇ pos¿¡ ±â·ÏÇÏ°í ¼³¸íÀº data¿¡ ¸Þ¸ð¸®¸¦ ÇÒ´çÇÏ¿© ±â·ÏÇÑ´Ù. ´Ü, ÀÌ ±×·ì ·¹ÄÚµå´Â ±×·ìÀÇ Çì´õÀÏ °æ¿ì¸¸ ÀÛ¼ºÇÑ´Ù. ´Ù¸¥ ±×·ì¿¡ ÁßøµÈ ±×·ìÀº ¸ñ·Ï¿¡ ³ªÅ¸³ªÁö ¾Ê±â ¶§¹®¿¡ ¼³¸íÀ» µû·Î ºÙÀÏ ÇÊ¿ä°¡ ¾ø´Ù. ±×·ì¿¡ ¼ÓÇÑ ±×·ìÀº ´õ ÀÌ»ó ±×·ìÀÌ ¾Æ´Ï¸ç ±×·ìÀ» ±¸¼ºÇÏ´Â ±¸¼º¿øÀÏ »ÓÀÌ´Ù.

±×·ìÀ» ½ÃÀÛÇÏ´Â StartUndoGroup ÇÔ¼öÀÇ ¿øÇüÀÌ ¼öÁ¤µÇ¾úÀ¸¹Ç·Î ÀÌ ÇÔ¼ö¸¦ È£ÃâÇÏ´Â ¸ðµç ºÎºÐ¿¡¼­ ±×·ìÀ» ½ÃÀÛÇÒ ¶§ id¿Í ÇÊ¿äÇÒ °æ¿ì ¼³¸í ¹®ÀÚ¿­À» Á¦°øÇØ¾ß ÇÑ´Ù. StartUndoGroup¿¡ Àμö¸¸ Ãß°¡ÇÏ¸é µÈ´Ù. ´ëºÎºÐ ApiEditText.cpp¿¡ ÀÖ´Ù.

 

À§Ä¡

¼³¸í

OnChar

OnImeComposition

InsertText

pFrame->StartUndoGroup(1);

IDM_AE_PASTE

pFrame->StartUndoGroup(2);

ChangeCase

pFrame->StartUndoGroup(3);

RemoveExtraSpace

pFrame->StartUndoGroup(4);

BlockIndent

pFrame->StartUndoGroup(5);

Dangeun.cppÀÇ OnUser2

pSi->Ae.StartUndoGroup(6);

CApiEditHexa::OnChar

pFrame->StartUndoGroup(7);

 

´ÙÀ½ ¼¼ ÇÔ¼ö´Â Á» ´õ ÀÚ¼¼ÇÑ ¼³¸íÀ» ºÙÀ̱â À§ÇØ ±¸Á¶°¡ ¾à°£ ¹Ù²î±âµµ ÇÑ´Ù. ¿¹¸¦ µé¿© ºí·Ï µé¿©¾²±âÀÇ °æ¿ì µé¿©¾²±âÀÎÁö ³»¾î¾²±âÀÎÁö¸¦ ±¸ºÐÇØ¾ß Çϸç InsertComment ÇÔ¼öÀÇ °æ¿ì ÁÖ¼®È­¿Í ÁÖ¼® ÇØÁ¦¸¦ µ¿½Ã¿¡ ÇÏ°í ÀÖÀ¸¹Ç·Î Àü´ÞµÈ Àμö¿¡ µû¶ó ¼³¸íÀ» ´Þ¸®ÇØ¾ß ÇÑ´Ù.

 

void CApiEditText::ProcessIndent(TCHAR ch)

{

     TCHAR szIndent[4096];

     int toff;

     int tlen;

     BOOL bAllSpace;

     int nTab;

 

     if (ch == '\r') {

          if (IsPrevParaBlockOpen(off)) {

              MakeIndentString(1,szIndent,4096);

              pFrame->StartUndoGroup(9);

          } else {

              lstrcpy(szIndent,"");

              pFrame->StartUndoGroup(8);

          }

        pFrame->StartUndoGroup();

     ....

     if (ch!='\r' && tlen && off >= tlen) {

          ....

                   pFrame->StartUndoGroup(10);

 

int CApiEditText::ReplaceText(int nPos, TCHAR *what, DWORD dwFlag, TCHAR *to)

{

     TCHAR szDesc[1024];

     ....

              wsprintf(szDesc," (%s -> %s)",what,to);

              pFrame->StartUndoGroup(11,szDesc);

 

void CApiEditText::ConvertSpaceTab(BOOL bToSpace)

{

     ....

     if (bToSpace) {

          ....

          pFrame->StartUndoGroup(12);

     } else {

          ....

          pFrame->StartUndoGroup(13);

     }

    pFrame->StartUndoGroup();

 

void CApiEditText::InsertComment(BOOL bUnComment)

{

     if (!bUnComment) {

          ....

          pFrame->StartUndoGroup(14);

     } else {

          ....

          pFrame->StartUndoGroup(15);

     }

    pFrame->StartUndoGroup();

 

±×·ìÀ» ±¸¼ºÇÒ ¶§¸¶´Ù Ãë¼Ò ·¹Äڵ忡 ±×·ì ¼³¸íÀ» À§ÇÑ ·¹Äڵ带 ÀÛ¼ºÇϹǷΠ¸Þ¸ð¸®´Â Á¶±Ý ´õ ¾²°Ô µÉ °ÍÀÌ´Ù. °¢ ±×·ì µ¿ÀÛÀÌ ±¸Ã¼ÀûÀ¸·Î ¾î¶² µ¿ÀÛÀÎÁö´Â º°µµÀÇ ¹®ÀÚ¿­ ¹è¿­À» ÀÛ¼ºÇÑ´Ù. ´ÙÀ½ ¹è¿­À» Dangeun.cppÀÇ ¼±µÎ¿¡ Á¤ÀÇÇÑ´Ù.

 

TCHAR arGroupDesc[50][32]={"",

     "¼±Åà ´ëü",

     "¼±Åà ´ëü ºÙ¿© ³Ö±â",

     "´ë¼Ò¹®ÀÚ º¯°æ",

     "¿©ºÐ °ø¹é Á¦°Å",

     "ºí·Ï µé¿©¾²±â",               // 5

     "¸ðµÎ ¹Ù²Ù±â",

     "ÀÌÁø ¹ÙÀÌÆ® ÆíÁý",

     "ÀÚµ¿ µé¿©¾²±â",

     "¹®¹ý µé¿©¾²±â",

     "¹®¹ý ³»¾î¾²±â",               // 10

     "¹Ù²Ù±â",

     "ÅÇÀ» °ø¹éÀ¸·Î",

     "°ø¹éÀ» ÅÇÀ¸·Î",

     "ÁÖ¼®À¸·Î",

     "ÁÖ¼® Á¦°Å",                     // 15

     "¿­ »èÁ¦",

     "¿­ ºÙ¿©³Ö±â",

     "¿­ º¹»ç",

     "¿­ À̵¿",

     "¿­ ´ë¼Ò¹®ÀÚ º¯°æ",                // 20

     "¸ÅÅ©·Î ½ÇÇà",

     "»ó¿ë±¸ »ðÀÔ",

     "ÀÚµ¿ »ó¿ë±¸ »ðÀÔ",

     "»èÁ¦-½º¸¶Æ® °ø¹é",

     "ºÙ¿© ³Ö±â",                     // 25

     "º¹»ç",

     "À̵¿",

     "¹®´Ü º´ÇÕ",

     "¹®´Ü ºÐÇÒ",

     "¹®´Ü ¼öÆò Á¤·Ä",                   // 30

     "¹®´Ü Å©±â¼ø Á¤·Ä",

     "¹®´Ü ºóÁÙ Á¶Á¤",

};

 

Áö±Ý ´çÀå Á¤ÀǵÇÁö ¾ÊÀº ±×·ì µ¿ÀÛ¿¡ ´ëÇÑ ¼³¸íµµ ¹Ì¸® ÀÛ¼ºÇØ ³õ¾Ò´Ù. ±×·ì µ¿ÀÛÀÌ ´õ ´Ã¾î³ª¸é ÀÌ ¹è¿­ÀÇ Å©±â¿Í ÃʱâÈ­ ¹®ÀÚ¿­µµ °°ÀÌ ´Ã¾î³¯ °ÍÀÌ´Ù. Ãë¼Ò ·¹ÄÚµåÀÇ actionÀÌ UR_GROUPÀÌ°í pos°¡ 5ÀÌ¸é ºí·Ï µé¿©¾²±â µ¿ÀÛ¿¡ ´ëÇÑ ±×·ìÀÓÀ» ¾Ë ¼ö ÀÖ´Ù. ±×·ì µ¿ÀÛ¿¡ ´ëÇØ Á¤¼öÇüÀ¸·Î id¸¦ ºÙÀÌ°í È£½ºÆ®°¡ id¿¡ ´ëÇÑ ¼³¸í ¹®ÀÚ¿­À» Á¦°øÇÏ´Â ÀÌÀ¯´Â ´Ù±¹¾î ¹öÀüÀ» ½±°Ô ¸¸µé±â À§Çؼ­ÀÌ´Ù.

È£½ºÆ®´Â ¹®ÀÚ¿­ ¸®¼Ò½º¸¦ ¹Ù²Ù¸é ´Ù¸¥ ¾ð¾î¸¦ ¾µ ¼ö ÀÖ´Ù. ±×·¯³ª ÄÁÆ®·ÑÀº ¸®¼Ò½º¸¦ °¡ÁöÁö ¾Ê±â ¶§¹®¿¡ ´Ù¸¥ ¾ð¾î¸¦ Áö¿øÇÏ·Á¸é ¹«Ã´ ¹ø°Å·Î¿ÍÁø´Ù. ±×·¡¼­ ApiEdit´Â ±×·ì µ¿ÀÛ¿¡ ´ëÇÑ ¼³¸íÀ» Á÷Á¢ ¹®ÀÚ¿­·Î ´ÞÁö ¾Ê°í ÀÏ·Ã ¹øÈ£·Î Á¤ÀÇÇϱ⸸ ÇÑ´Ù. ÇöÀç±îÁö ApiEditÀÇ ¼Ò½º¿¡¼­ ¹®ÀÚ¿­À» Á÷Á¢ »ç¿ëÇÑ °æ¿ì´Â Æ˾÷ ¸Þ´ºÀÇ "À߶󳻱â", "º¹»ç" °°Àº ¸Þ´º ĸ¼Ç¹Û¿¡ ¾ø´Ù. ÀÌ ¹®ÀÚ¿­µµ ¹°·Ð ³ªÁß¿¡´Â ´Ù¸¥ ¹æ½ÄÀ¸·Î ±¸Çϵµ·Ï ¹Ù²Ù¾î¾ß ÇÑ´Ù. ÄÁÆ®·ÑÀÌ Á÷Á¢ ¹®ÀÚ¿­À» ´Ù·ç´Â °ÍÀº ÁÁÁö ¾Ê´Ù.

±×·ì ½ÃÀÛ¸¸ ÇØ ³õ°í ½ÇÁ¦ ·¹Äڵ带 ±â·ÏÇÏÁö ¾Ê´Â °æ¿ì°¡ ÀÖ´Ù. ¿¹¸¦ µé¾î ÀÚµ¿ µé¿©¾²±âÀÇ °æ¿ì ±×·ì ½ÃÀÛÀº ÇßÁö¸¸ ÀÚµ¿ µé¿©¾²±â ÇÒ ³»¿ëÀÌ ¾øÀ¸¸é ½ÇÁ¦ ·¹Äڵ尡 ±â·ÏµÇÁö ¾Ê´Â´Ù. ¸ðµÎ ¹Ù²Ù±âÀÇ °æ¿ì ÀÏ´Ü ±×·ìÀ» ½ÃÀÛÇÏÁö¸¸ ã´Â ³»¿ëÀÌ ¾øÀ¸¸é ±×·ì Çì´õ¸¸ ÀÖ°í º»Ã¼´Â ¾øÀ» °ÍÀÌ´Ù. ³ªÈ¦·Î ±×·ìÀº »ç½Ç Á¸Àç °¡Ä¡°¡ ¾øÁö¸¸ Äڵ带 °£´ÜÇÏ°Ô Çϱâ À§Çؼ­´Â ºÒ°¡ÇÇÇÏ°Ô ÀϽÃÀûÀ¸·Î »ý¼ºµÉ ¼ö¹Û¿¡ ¾ø´Ù. ±×·ìÀ» ½ÃÀÛÇÏ´Â ½ÃÁ¡¿¡¼­ ½ÇÁ¦ ÆíÁý ¿©ºÎ¸¦ ÆÇ´ÜÇϱⰡ ´ë´ÜÈ÷ ¾î·Æ´Ù. ±×·¡¼­ ÀÏ´Ü ³ªÈ¦·Î ±×·ìÀ» ±â·ÏÇØ ³õ°í ±×·ìÀ» ³¡³¾ ¶§ ÀÌ ±×·ìÀÌ ½ÇÁ¦ ÆíÁý ·¹Äڵ带 °¡Áö°í ÀÖ´ÂÁö Á¡°ËÇØ º¸°í ºó ·¹ÄÚµåÀÌ¸é »èÁ¦ÇÑ´Ù.

 

void CApiEdit::EndUndoGroup()

{

     URnest--;

     if (URnest==0) {

        if (pUR[nowur].action == UR_GROUP) {

           pUR[nowur].action=UR_NONE;

        }

          URtick=0;

     }

}

 

±×·ìÀ» ³¡³¾ ¶§ nowurÀÚ¸®°¡ ±×·ì Çì´õ¶ó¸é ºó ±×·ìÀ̹ǷΠÀÌ ·¹ÄÚµåÀÇ actionÀ» UR_NONEÀ¸·Î ¸¸µé¾î ´ÙÀ½ ·¹ÄÚµå ÀÛ¼º½Ã Àç»ç¿ëÇÑ´Ù. ÇÒ´çÇØ ³õÀº ¸Þ¸ð¸®³ª pos, tick°ªÀº ±×´ë·Î µÎ¾îµµ ¾îÂ÷ÇÇ ´ÙÀ½¿¡ »õ·Î¿î °ªÀ¸·Î ´ëÀԵǹǷΠ»ó°ü¾ø´Ù. ±×·ìÀ» ³¡³¾ ¶§ NextRecord´Â È£ÃâÇÏÁö ¾Ê´Âµ¥ ¹Ù·Î ´ÙÀ½¹ø ·¹Äڵ尡 ±×·ìÀÇ ³¡ ·¹ÄÚµå¿Í º´ÇÕµÉ ¼ö Àֱ⠶§¹®ÀÌ´Ù. ¿¹¸¦ µé¾î abc¸¦ ¼±ÅÃÇØ ³õ°í def·Î ´ëüÇÒ ¶§ abc »èÁ¦¿Í dÀÔ·ÂÀÌ ÀÏ´Ü ±×·ìÀ¸·Î ÀÛ¼ºµÇ¸ç À̾îÁö´Â ef »ðÀÔÀÌ d»ðÀÔ°ú º´ÇյǾî¾ß abc »èÁ¦, def »ðÀÔÀÌ ÇÑ ±×·ìÀÌ µÉ ¼ö ÀÖ´Ù.

³ª.±×·ì °ü¸® ÇÔ¼ö

´ÙÀ½ ÇÔ¼öµéÀº ÆíÁý ±×·ìÀ» °ü¸®ÇÏ´Â ÇÔ¼öµéÀÌ¸ç ´ÙÀ½ Ç×ÀÇ ÆíÁý ±â·Ïâ¿¡¼­ »ç¿ëÇÑ´Ù. FindGroupEnd´Â ±×·ìÀÇ ¸¶Áö¸· ·¹Äڵ带 ã´Â À¯Æ¿¸®Æ¼ ÇÔ¼öÀÌ´Ù. ƽ°ªÀÌ ´Ù¸¥ ÃÖÃÊÀÇ ·¹Äڵ带 ãÀº ÈÄ ¹Ù·Î Á÷ÀüÀÇ ·¹ÄÚµå ¹øÈ£¸¦ ÃëÇÏ¸é ¿©±â°¡ ±×·ìÀÇ ³¡ÀÌ´Ù.

 

int CApiEdit::FindGroupEnd(int idx)

{

     int i;

 

     for (i=idx+1;pUR[i].tick == pUR[idx].tick;i++);

     return i-1;

}

 

void CApiEdit::MultiUndo(int idx)

{

     for (;;) {

          if (CanUndo()) {

              Undo();

          } else {

              break;

          }

          if (nowur <= idx) {

              break;

          }

     }

}

 

void CApiEdit::MultiRedo(int idx)

{

     for (;;) {

          if (CanRedo()) {

              Redo();

          } else {

              break;

          }

          if (nowur > idx) {

              break;

          }

     }

}

 

MultiUndo, MutiRedo´Â Àμö·Î Àü´Þ¹ÞÀº idx¹ø±îÁö ÇѲ¨¹ø¿¡ Undo, RedoÇÑ´Ù. idx¿¡ À̸¦ ¶§±îÁö Undo, Redo¸¦ °è¼Ó È£ÃâÇÏ´Â °£´ÜÇÑ ±¸Á¶·Î µÇ¾î ÀÖÀ¸¸ç ±×¸¸µÑ ½ÃÁ¡À» ÆÇ´ÜÇÏ´Â ºÎµîÈ£¿¡¸¸ ÁÖÀÇÇÏ¸é µÈ´Ù. MuitiUndo´Â idxº¸´Ù Å©Áö ¾ÊÀ» ¶§ Å»ÃâÇϹǷΠ<=·Î ºñ±³, MultiRedo´Â idxº¸´Ù Ŭ ¶§ Å»ÃâÇϹǷΠ>·Î ºñ±³ÇÑ´Ù.

ÀÌ Â÷ÀÌ´Â Undo¿Í Redo ÇÔ¼öÀÇ ±¸Á¶ Â÷ÀÌ¿¡¼­ ±âÀÎÇÏ¸ç ´õ ±Ùº»ÀûÀ¸·Î´Â nowurÀÌ ¾îµð¸¦ °¡¸®Å°°í Àִ°¡ÀÇ Á¤ÀÇ¿¡ ÀÇÇØ °áÁ¤µÈ °ÍÀÌ´Ù. Undo´Â Å»Ãâ Á¡°ËÀ» ÇÑ ÈÄ nowur--·Î ´ÙÀ½ ·çÇÁ¸¦ µ¹±â ¶§¹®¿¡ Ãë¼ÒÈÄ ±× ÀÚ¸®¿¡ ¸Ó¹®´Ù. ¹Ý¸é Redo´Â ¹«Á¶°Ç NextRecordÈ£ÃâÀ» ¸ÕÀúÇÏ°í Å»Ãâ Á¡°ËÀ» ÇϹǷΠÀç½ÇÇà ÈÄ ´ÙÀ½ ·¹ÄÚµå·Î À̵¿ÇØ ÀÖ°Ô µÈ´Ù.

±×·¡¼­ nowur°ú idx°¡ °°¾ÆÁø »óȲ¿¡ ´ëÇÑ Ã³¸®°¡ ´Þ¶óÁö´Â °ÍÀÌ´Ù. MultiUndo´Â idx±îÁö ÀÌ¹Ì Ãë¼ÒµÇ¾úÀ¸¹Ç·Î À̶§ Å»ÃâÇÑ´Ù. MultiRedo´Â ¾ÆÁ÷ idx±îÁö Àç½ÇÇàÇÑ °ÍÀÌ ¾Æ´Ï¹Ç·Î Çѹø ´õ Redo¸¦ È£ÃâÇØ¾ß ÇÑ´Ù. ÀÌ·¸°Ô ¼³¸íÀ» ÀÐÀ¸¸é Á¤¸» º¹ÀâÇØ º¸ÀÌÁö¸¸ ½ÇÁ¦·Î ¹®Á¦¸¦ Ç®¾î º¸¸é º° °Íµµ ¾Æ´Ï´Ù. óÀ½¿¡ ´ëÃæ ¸¸µé¾î ³õ°í µð¹ö°Å·Î µ¹·Á º¸¸é ¾î¶² ¿¬»êÀÚ·Î ºñ±³¸¦ ÇØ¾ß ÇÒÁö ½±°Ô °áÁ¤ÇÒ ¼ö ÀÖ´Ù.

±×·ì Çì´õ ·¹Äڵ尡 Ãß°¡µÇ¾úÁö¸¸ Undo, Redo µî Ãë¼Ò ·¹Äڵ带 °ü¸® ¹× »ç¿ëÇÏ´Â ÇÔ¼öµéÀº ¼öÁ¤ÇÒ ÇÊ¿ä°¡ ¾ø´Ù. Undo, Redo ÇÔ¼ö´Â action¿¡ µû¶ó ÀûÀýÇÑ µ¿ÀÛÀ» Çϴµ¥ actionÀÇ switch ¹®¿¡ case UR_GROUP¿¡ ´ëÇÑ Ã³¸®°¡ ¾ø±â ¶§¹®¿¡ ÀÚ¿¬È÷ ¹«½ÃµÈ´Ù.

´Ù.ÆíÁý ±â·Ïâ

ÆíÁý ±â·Ïâ Ç¥½Ã¸¦ À§ÇØ Åø¹ÙÀÇ Ãë¼Ò, Àç½ÇÇà ¹öÆ°ÀÇ ½ºÅ¸ÀÏÀ» µå·Ó ´Ù¿îÀ¸·Î º¯°æÇØ ³õ¾Ò´Ù. ÀÌ ¹öÆ°À» ´©¸£¸é ÆíÁý °úÁ¤À» Ç¥½ÃÇÏ´Â ÀÛÀº ´ëÈ­»óÀÚ¸¦ ¿­ °ÍÀÌ´Ù. µå·Ó ´Ù¿î Åø¹Ù¸¦ ¿­¸é WM_NOTIFY ÅëÁö ¸Þ½ÃÁö°¡ Àü´ÞµÇ´Âµ¥ ÀÌ ¸Þ½ÃÁö¸¦ ¹Þ¾ÒÀ» ¶§ ÆíÁý ±â·ÏÀ» º¸¿©ÁØ´Ù.

 

static HWND hEdRecDlg;

 

void OnNotify(HWND hWnd,WPARAM wParam,LPARAM lParam)

{

     ....

     switch (hdr->code) {

     case TTN_GETDISPINFO:

          ....

     case TBN_DROPDOWN:

          hEdRecDlg=CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_EDITRECORD),

              hWnd, (DLGPROC)EditRecordProc,((NMTOOLBAR *)lParam)->iItem);

          break;

     }

}

 

ÆíÁý ±â·ÏÀ» Ç¥½ÃÇÏ´Â ÀÛÀº Æ˾÷ ´ëÈ­»óÀÚ¸¦ ¸ðµ¨¸®½º·Î ¸¸µç´Ù. Æ÷Ä¿½º¸¦ ÀÒÀ¸¸é Áï½Ã »ç¶óÁ®¾ß ÇϹǷΠ¸ðµ¨¸®½º·Î ¸¸µé¾úÀ¸¸ç ¸ÞÀÎ ¸Þ½ÃÁö ·çÇÁ¿¡¼­ ¸ðµ¨¸®½º ´ëÈ­»óÀÚ·Î ¸Þ½ÃÁö¸¦ º¸³»¾ß ÇÑ´Ù.

 

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance

            ,LPSTR lpszCmdParam,int nCmdShow)

{

     ....

              if ((!IsWindow(g_FindDlg) || !IsDialogMessage(g_FindDlg,&Message)) &&

               (!IsWindow(hEdRecDlg) || !IsDialogMessage(hEdRecDlg,&Message)) ) {

                   if (!TranslateMDISysAccel(g_hMDIClient, &Message)) {

                        if (!TranslateAccelerator(hWnd,hAccel,&Message)) {

                            TranslateMessage(&Message);

                            DispatchMessage(&Message);

                        }

                   }

              }

 

ÆíÁý ±â·Ï ÁßÀÇ ÅÇÀ̳ª °³Çà ÄÚµå µîÀ» ±×´ë·Î Ãâ·ÂÇÏ¸é ±×·¡ÇÈ ¹®ÀڷΠǥ½ÃµÇ¹Ç·Î ÀÌ Á¦¾î Äڵ带 ´«¿¡ º¸ÀÌ´Â ´Ù¸¥ ¹®ÀÚ·Î ´ëüÇؼ­ Ç¥½ÃÇÏ´Â °ÍÀÌ ´õ º¸±â¿¡ ÁÁ´Ù. ´ÙÀ½ ÇÔ¼ö¸¦ Util.cpp¿¡ ÀÛ¼ºÇÑ´Ù.

 

// Á¦¾îÄڵ带 ÀÐÀ» ¼ö ÀÖ´Â ¹®ÀÚ·Î º¯È¯ÇÑ´Ù.

void ReplaceCtrlString(TCHAR *src, int slen, TCHAR *dest, int dlen)

{

     TCHAR *s,*d;

     TCHAR *dest2;

 

     s=src;

     if (dest==NULL) {

          d=dest2=(TCHAR *)malloc(1024);

          dlen=1024;

     } else {

          d=dest;

     }

 

     memset(d,0,dlen);

     for (;*s;d++, s++) {

          if (s-src >= slen) {

              break;

          }

          if ((dest && d-dest >= dlen-1) || (dest==NULL && d-dest2 >= dlen-1)) {

              break;

          }

 

          if (*s == '\r' && s-src+1 < slen && s[1] == '\n') {

              lstrcat(d,"[°³Çà]");

              d+=5;

              s++;

          } else if (*s == '\t') {

              lstrcat(d,"[ÅÇ]");

              d+=3;

          } else {

              if (IsDBCSLeadByte(*s)) {

                   *d++=*s++;

                   *d=*s;

              } else {

                   if (*s >= 0x20 && *s <= 0x7e) {

                        *d=*s;

                   } else {

                        *d='.';

                   }

              }

          }

     }

     if (dest==NULL) {

          lstrcpy(src,dest2);

          free(dest2);

     }

}

 

ReplaceCtrlString ÇÔ¼ö´Â ÅÇ, °³Çà Äڵ带 ÀÐÀ» ¼ö ÀÖ´Â ¹®ÀÚ¿­·Î º¯°æÇÏ¸ç ±× ¿ÜÀÇ ÀμâÇÒ ¼ö ¾ø´Â Á¦¾î ÄÚµå´Â .À¸·Î Ç¥½ÃÇÑ´Ù. ÀÌÁø ÆÄÀÏÀ» ´Ù·ê ¼ö Àֱ⠶§¹®¿¡ ÀÓÀÇÀÇ ¹®ÀÚ Äڵ尡 ¿Ã ¼ö ÀÖÀ¸¹Ç·Î ¸ðµç Äڵ忡 ´ëÇØ ´«¿¡ º¸ÀÌ´Â ¹®ÀÚ¿­·Î º¯È¯ÇØ¾ß ÇÑ´Ù. src¸¦ º¯È¯ÇÏ¿© dest¿¡ º¹»çÇ쵂 dest°¡ NULLÀ̸é Àӽà ¹öÆÛ¸¦ ÇÒ´çÇÏ¿© º¯È¯ÇÏ°í ±× °á°ú¸¦ ´Ù½Ã src¿¡ º¹»çÇÑ´Ù. À̶§ src´Â º¯È¯ ÈÄÀÇ ¹®ÀÚ¿­À» ÀúÀåÇÒ ¼ö ÀÖÀ»¸¸Å­ ÃæºÐÇÑ ±æÀ̸¦ °¡Á®¾ß ÇÑ´Ù. È£ÃâÇÏ´Â Ãø¿¡¼­´Â src¿Í dest¸¦ µ¿½Ã¿¡ Àü´ÞÇÏ¿© src¸¦ À¯ÁöÇÑ Ã¤·Î º¯È¯ °á°ú¸¦ ¹ÞÀ» ¼öµµ ÀÖ°í src¸¸ Àü´ÞÇÏ¿© º¯È¯ °á°ú¸¦ src¿¡ ´Ù½Ã ä¿ì°Ô ÇÒ ¼ö ÀÖ´Ù.

´ÙÀ½Àº ÆíÁý ±â·Ï ´ëÈ­»óÀÚ ÇÁ·Î½ÃÀú¸¦ ÀÛ¼ºÇÑ´Ù. ÀÌ ´ëÈ­»óÀÚ´Â Ãë¼Ò ¹× Àç½ÇÇà ¹öÆ° µÑ ´Ù¿¡ ´ëÇØ µ¿ÀÛÇϴµ¥ lParamÀ¸·Î Åø¹Ù ¹öÆ°ÀÇ ID¸¦ Àü´Þ¹Þ¾Æ ´­·¯Áø ¹öÆ°¿¡ µû¶ó ¸ñ·ÏÀ» ´Ù¸£°Ô ÀÛ¼ºÇÑ´Ù. ¾îÂ÷ÇÇ µÑ ´Ù Ãë¼Ò ·¹ÄÚµåÀÇ ¸ñ·ÏÀ» Ç¥½ÃÇϹǷΠÃâ·Â °úÁ¤Àº °ÅÀÇ ºñ½ÁÇÒ °ÍÀÌ´Ù.

 

BOOL CALLBACK EditRecordProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

     static BOOL bUndo;

     static HWND hList;

     RECT rt;

     LVCOLUMN COL;

     SInfo *pSi;

     HWND hActive;

     int idx, count, Inc, idx2;

     UndoRecord *pUR;

     LVITEM LI;

     TCHAR szAct[12], szCon[1024];

 

     switch(iMessage) {

     case WM_INITDIALOG:

          if (lParam == IDM_EDIT_UNDO) {

              bUndo=TRUE;

              Inc=-1;

              SetDlgItemText(hDlg,IDC_MULTIUR,"¼±Åà µ¿ÀÛ±îÁö Ãë¼Ò");

          } else {

              bUndo=FALSE;

              Inc=1;

              SetDlgItemText(hDlg,IDC_MULTIUR,"¼±Åà µ¿ÀÛ±îÁö Àç½ÇÇà");

          }

 

          SendMessage(hToolBar,TB_GETITEMRECT,bUndo ? 8:9,(LPARAM)&rt);

          rt.top=rt.bottom+2;

          ClientToScreen(g_hFrameWnd,(LPPOINT)&rt);

          SetWindowPos(hDlg,HWND_NOTOPMOST,rt.left,

              rt.top,0,0,SWP_NOSIZE);

 

          hList=GetDlgItem(hDlg,IDC_UNDOLIST);

          COL.mask=LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;

          COL.fmt=LVCFMT_LEFT;

          COL.cx=40;

          COL.pszText="µ¿ÀÛ";

          COL.iSubItem=0;

          ListView_InsertColumn(hList,0,&COL);

 

          COL.cx=145;

          COL.pszText="³»¿ë";

          COL.iSubItem=1;

          ListView_InsertColumn(hList,1,&COL);

 

          ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT);

          hActive=(HWND)SendMessage(g_hMDIClient,WM_MDIGETACTIVE,0,NULL);

          pSi=(SInfo *)GetWindowLong(hActive,0);

 

          for (idx=pSi->Ae.nowur, count=0;;idx+=Inc) {

              pUR=&pSi->Ae.pUR[idx];

              if (bUndo) {

                   if (pUR->action == UR_NONE || pUR->status == UR_CANCELED)

                        continue;

              } else {

                   if (pUR->action == UR_NONE)

                        break;

              }

 

              if (bUndo && pUR->action != UR_GROUP && pUR->tick) {

                   for (;idx >= 0;idx--) {

                        if (pSi->Ae.pUR[idx].action==UR_GROUP && pSi->Ae.pUR[idx].tick==pUR->tick) {

                            break;

                        }

                   }

                   if (idx < 0) {

                        break;

                   }

                   switch (pSi->Ae.pUR[idx].pos) {

                   case 8:

                   case 9:

                        for (idx2=idx;;idx2++) {

                            if (pSi->Ae.pUR[idx2].action==UR_INSERT)

                                 break;

                        }

                        lstrcpy(szAct,"»ðÀÔ");

                        ReplaceCtrlString(pSi->Ae.pUR[idx2].data,pSi->Ae.pUR[idx2].len,szCon,1024);

                        break;

                   default:

                        lstrcpy(szAct,"±×·ì");

                        lstrcpy(szCon,arGroupDesc[pSi->Ae.pUR[idx].pos]);

                        if (pSi->Ae.pUR[idx].data) {

                            lstrcat(szCon,pSi->Ae.pUR[idx].data);

                        }

                        break;

                   }

              } else if (bUndo==FALSE && pUR->action == UR_GROUP) {

                   switch (pSi->Ae.pUR[idx].pos) {

                   case 8:

                   case 9:

                        for (idx2=idx;;idx2++) {

                            if (pSi->Ae.pUR[idx2].action==UR_INSERT)

                                 break;

                        }

                        lstrcpy(szAct,"»ðÀÔ");

                        ReplaceCtrlString(pSi->Ae.pUR[idx2].data,pSi->Ae.pUR[idx2].len,szCon,1024);

                        break;

                   default:

                        lstrcpy(szAct,"±×·ì");

                        lstrcpy(szCon,arGroupDesc[pUR->pos]);

                        if (pUR->data) {

                            lstrcat(szCon,pUR->data);

                        }

                        break;

                   }

                   idx=pSi->Ae.FindGroupEnd(idx);

              } else {

                   switch (pUR->action) {

                   case UR_INSERT:

                        lstrcpy(szAct,"»ðÀÔ");

                        ReplaceCtrlString(pUR->data,pUR->len,szCon,1024);

                        break;

                   case UR_DELETE:

                        lstrcpy(szAct,"»èÁ¦");

                        ReplaceCtrlString(pUR->data,pUR->len,szCon,1024);

                        break;

                   case UR_MOVE:

                        lstrcpy(szAct,"À̵¿");

                        wsprintf(szCon,"%d -> %d(%d¹ÙÀÌÆ®)",pUR->pos,pUR->dest[0],pUR->dest[1]);

                        break;

                   }

              }

 

              LI.mask=LVIF_TEXT | LVIF_PARAM;

              LI.iItem=count;

              LI.iSubItem=0;

              LI.lParam=idx;

              LI.pszText=szAct;

              ListView_InsertItem(hList,&LI);

              ListView_SetItemText(hList,count,1,szCon);

              if ((bUndo && idx == 0) || count == 200) {

                   break;

              }

              count++;

          }

 

          SetFocus(hList);

          return FALSE;

     case WM_ACTIVATE:

          if (LOWORD(wParam) == WA_INACTIVE) {

              PostMessage(hDlg,WM_COMMAND,MAKEWPARAM(IDCANCEL,0),0);

              return TRUE;

          }

          break;

     case WM_COMMAND:

          switch (LOWORD(wParam))   {

          case IDC_MULTIUR:

              idx=ListView_GetNextItem(hList,-1,LVNI_ALL | LVNI_SELECTED);

              if (idx != -1) {

                   LI.mask=LVIF_PARAM;

                   LI.iItem=idx;

                   ListView_GetItem(hList,&LI);

                   PostMessage(g_hFrameWnd,WM_USER+3,(WPARAM)bUndo,(LPARAM)LI.lParam);

              }

          case IDCANCEL:

              DestroyWindow(hDlg);

              return FALSE;

          }

          return FALSE;

     case WM_NOTIFY:

          LPNMHDR hdr;

          hdr=(LPNMHDR)lParam;

          if (hdr->hwndFrom == hList) {

              switch (hdr->code) {

              case NM_DBLCLK:

                   PostMessage(hDlg,WM_COMMAND,MAKEWPARAM(IDC_MULTIUR,0),0);

                   return TRUE;

              }

          }

          break;

     }

     return FALSE;

}

 

´ëÈ­»óÀÚ°¡ ¿­¸± ¶§ lParamÀ¸·Î ¾î¶² Åø ¹öÆ°ÀÌ ´­·¯Á³´ÂÁö ID¸¦ Àü´Þ¹Þ´Âµ¥ ÀÌ °ªÀ¸·ÎºÎÅÍ Ãë¼Ò ±â·ÏÀÎÁö, Àç½ÇÇà ±â·ÏÀÎÁö¸¦ ÆÇ´ÜÇÏ¿© bUndo ½ºÅÂƽ º¯¼ö¿¡ ÀúÀåÇÑ´Ù. WM_INITDIALOG¿¡¼­ ¸®½ºÆ® ºä ÄÁÆ®·ÑÀ» ÃʱâÈ­ÇÏ°í ÆíÁý ±â·ÏÀ» ¸®½ºÆ® ºä¿¡ Ãâ·ÂÇÑ´Ù. nowurºÎÅÍ ¼ø¼­´ë·Î Ãë¼Ò ·¹Äڵ带 ÀÐ¾î ±× ³»¿ëÀ» ¸®½ºÆ® ºä¿¡ µî·ÏÇß´Ù.

¸ñ·ÏÀ» ä¿ì´Â ¹æ¹ýÀº bUndo¿¡ µû¶ó ´Þ¶óÁø´Ù. ÀÏ´Ü nowur¿¡¼­ ¸ñ·ÏÀ» ÀÛ¼ºÇÒ ¹æÇâÀÌ ´Þ¶óÁö´Âµ¥ ÀÌ ¹æÇâÀº Incº¯¼ö°¡ ±â¾ïÇÑ´Ù. ¸ñ·ÏÀ» ä¿ì´Â for ·çÇÁ´Â nowur¿¡¼­ ½ÃÀÛÇؼ­ Inc ¹æÇâÀ¸·Î Áõ°¨Çϸ鼭 ¾Æ·¡ À§·Î À̵¿ÇÏ¸ç ¹ß°ßµÇ´Â ·¹Äڵ带 ¸®½ºÆ® ºä¿¡ ä¿î´Ù. Ãë¼Ò ¸ñ·ÏÀÎ °æ¿ì´Â ÀÌ¹Ì Ãë¼ÒµÈ ·¹Äڵ峪 ¾ÆÁ÷ ÀÛ¼ºµÇÁö ¾ÊÀº ·¹ÄÚµå´Â Ãë¼Ò ´ë»óÀÌ ¾Æ´Ï¹Ç·Î Ãë¼Ò °¡´ÉÇÑ ¸ñ·ÏÀ» ¸¸³¯ ¶§±îÁö °è¼Ó ·çÇÁÀÇ ¼±µÎ·Î º¸³»±â¸¸ ÇÑ´Ù. Àç½ÇÇà ¸ñ·ÏÀÎ °æ¿ì UR_NONEÀ» ¸¸³ª¸é ¸ñ·ÏÀÇ ³¡À̹ǷΠÀ̶§ ·çÇÁ¸¦ Á¾·áÇÑ´Ù.

±×·ì ·¹Äڵ带 ó¸®ÇÏ´Â ¹æ¹ýµµ »ó´çÈ÷ ´Ù¸£´Ù. Ãë¼Ò ¸ñ·ÏÀÇ °æ¿ì ±×·ì ¿ä¼Ò°¡ ³ªÅ¸³ª¸é ÀÏ´Ü ±×·ì Çì´õ¸¦ ã¾Æ Çì´õÀÇ ¼³¸íÀ» ÃëÇÑ´Ù. ´Ü, Ãë¼Ò ·¹ÄÚµå °³¼ö °ü¸® ±â´É¿¡ ÀÇÇØ ¿ä¼Ò¸¸ ³²°í Çì´õ´Â Àß·Á ³ª°£ °æ¿ì°¡ ÀÖÀ» ¼ö Àִµ¥ À̶§´Â ¸ñ·Ï ÀÛ¼ºÀ» ³¡³½´Ù. ±×·ì Çì´õÀÇ id°¡ 8, 9¹ø Áï µé¿©¾²±âÀÎ °æ¿ì´Â µé¿©¾²±â ÈÄ¿¡ »ðÀÔµÈ ¹®ÀÚ¿­°ú ÇÔ²² »ðÀÔÀ¸·Î ó¸®ÇÏ°í ³ª¸ÓÁö ±×·ìÀº "±×·ì" µ¿ÀÛÀÇ ¼³¸í ¹®ÀÚ¿­À» ³»¿ëÀ¸·Î ÃëÇÑ´Ù. Àç½ÇÇà ¸ñ·ÏÀÇ °æ¿ì ±×·ì Çì´õ¸¦ ¸ÕÀú ¸¸³ª´Âµ¥ À̶§´Â Çì´õÀÇ ¼³¸íÀ» ÃëÇÏ°í ±×·ìÀÇ ³¡À¸·Î À̵¿ÇÑ´Ù. ´ÙÀ½ ·çÇÁ¿¡¼­ idx¸¦ 1Áõ°¡½ÃÅ°¹Ç·Î Á¤È®ÇÏ°Ô ±×·ì ´ÙÀ½ ·¹ÄÚµåºÎÅÍ ¸ñ·ÏÀ» ÀÛ¼ºÇÏ°Ô µÉ °ÍÀÌ´Ù.

±×·ìÀÌ ¾Æ´Ñ »ðÀÔ, »èÁ¦, À̵¿ ·¹Äڵ忡 ´ëÇÑ ¸ñ·Ï ÀÛ¼ºÀº ¾ÆÁÖ Á÷°üÀûÀÌ´Ù. ¼³¸íÀ» °¢°¢ "»ðÀÔ", "»èÁ¦","À̵¿"À¸·Î ÀÛ¼ºÇÏ°í »ðÀÔ, »èÁ¦µÈ ¹®ÀÚ¿­À» ReplaceCtrlStringÀ¸·Î Á¦¾î Äڵ带 ó¸®ÇÑ ÈÄ ¸®½ºÆ® ºä¿¡ Ãß°¡ÇÏ°í À̵¿ÀÎ °æ¿ì´Â ¾îµð¼­ºÎÅÍ ¾îµð±îÁö ¸î ¹ÙÀÌÆ®¸¦ À̵¿Çß´ÂÁö¸¦ Ç¥½ÃÇÑ´Ù. ¸®½ºÆ® ºä¿¡ Ç׸ñÀ» Ãß°¡ÇÑ ÈÄ ·çÇÁ ³¡ Á¡°ËÀ» Çϴµ¥ Ãë¼Ò ¸ñ·Ï¿¡¼­ ·¹ÄÚµåÀÇ Ã³À½À» ¸¸³µ°Å³ª ÃÖ´ë °³¼ö°¡ 200°³¸¦ ³ÑÀ¸¸é ·çÇÁ¸¦ Á¾·áÇÑ´Ù. ÃÖ´ë 200°³±îÁöÀÇ µ¿ÀÛÀ» ÇѲ¨¹ø¿¡ Ãë¼ÒÇÒ ¼ö ÀÖ´Ù´Â ¶æÀÌ´Ù.

 

»ç¿ëÀÚ´Â ÆíÁý ±â·Ï ´ëÈ­»óÀÚ¿¡¼­ ÆíÁý ±â·ÏÀ» »ìÆì º¸°í ¾îµð±îÁö Ãë¼Ò ¶Ç´Â Àç½ÇÇàÀ» ÇÒ °ÍÀΰ¡¸¦ ¼±ÅÃÇÒ ¼ö ÀÖ´Ù. »ç¿ëÀÚ°¡ ¸ñ·ÏÀ» ´õºí Ŭ¸¯Çϰųª Ãë¼Ò ¹öÆ°À» ´©¸£¸é WM_USER+3 ¸Þ½ÃÁö¸¦ ºÎ¸ð À©µµ¿ìÀÇ ¸Þ½ÃÁö Å¥¿¡ ºÙÀδÙ. À̶§ wParamÀ¸·Î´Â Ãë¼ÒÀÎÁö Àç½ÇÇàÀÎÁö¸¦ ¾Ë¸®´Â bUndoÀÇ °ªÀÌ Àü´ÞµÇ°í lParamÀ¸·Î´Â ¸®½ºÆ®ºä¿¡¼­ ¼±ÅÃµÈ ·¹ÄÚµåÀÇ À妽º¸¦ Àü´ÞÇÑ´Ù. SendMessage·Î ¸Þ½ÃÁö¸¦ º¸³»Áö ¾Ê°í PostMessage·Î ºÙÀÌ´Â ÀÌÀ¯´Â ÀÏ´Ü ÀÌ ´ëÈ­»óÀÚ¸¦ ´ÝÀº ÈÄ¿¡ Ãë¼Ò ¹× Àç½ÇÇàÀ» ÇØ¾ß Çϱ⠶§¹®ÀÌ´Ù. ±×·¡¼­ case IDC_MULTIUR: ´ÙÀ½¿¡´Â break°¡ ¾ø´Ù.

ÆíÁý ±â·Ï ´ëÈ­»óÀÚ´Â ¸ðµ¨¸®½º·Î ¿­¸®´Âµ¥ »ç¿ëÀÚ°¡ ¹Ýµå½Ã Ãë¼Ò ¹× Àç½ÇÇàÀ» Çϱâ À§Çؼ­¸¸ ¿©´Â °ÍÀº ¾Æ´Ï´Ù. ¶§·Î´Â ¾î¶² ÆíÁýÀ» Çß´ÂÁö È®Àθ¸ Çϱâ À§ÇØ ¿­ ¼öµµ ÀÖÀ¸¹Ç·Î ÀÚ½ÅÀÌ ºñÈ°¼ºÈ­µÇ¸é Áï½Ã âÀ» ´Ý¾Æ¾ß ÇÑ´Ù. ±×·¡¼­ WM_ACTIVATE¿¡¼­ ºñÈ°¼ºÈ­µÉ ¶§ Àڽſ¡°Ô IDCANCEL ¸Þ½ÃÁö¸¦ ó¸®ÇÏ¿© ´ëÈ­»óÀÚ¸¦ ´Ý´Â´Ù. WM_ACTIVATE¿¡¼­ ¹Ù·Î DestroyWindow·Î ÀÚ±â ÀÚ½ÅÀ» Æı«ÇØ ¹ö¸®¸é ¸ÞÀÎ À©µµ¿ì°¡ È°¼ºÈ­µÇÁö ¾ÊÀ¸¹Ç·Î ¹Ýµå½Ã IDCANCEL À» Å¥¿¡ ºÙ¿© Á¤»óÀûÀÎ °úÁ¤À¸·Î Æı«ÇØ¾ß ÇÑ´Ù. ¸ÞÀÎ À©µµ¿ì´Â ÀÌ ´ëÈ­»óÀÚ°¡ º¸³»´Â WM_USER+3 ¸Þ½ÃÁö¸¦ ó¸®ÇÑ´Ù.

 

LRESULT CALLBACK DGWndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

     switch(iMessage) {

          ....

        case WM_USER+3:OnUser3(hWnd,wParam,lParam);return 0;

     }

     return(DefFrameProc(hWnd,g_hMDIClient,iMessage,wParam,lParam));

}

 

void OnUser3(HWND hWnd,WPARAM wParam,LPARAM lParam)

{

     SInfo *pSi;

     HWND hActive;

 

     hActive=(HWND)SendMessage(g_hMDIClient, WM_MDIGETACTIVE,0,NULL);

     if (hActive) {

          pSi=(SInfo *)GetWindowLong(hActive,0);

          if (wParam == TRUE) {

              pSi->Ae.MultiUndo(lParam);

          } else {

              pSi->Ae.MultiRedo(lParam);

          }

     }

}

 

wParam°ª¿¡ µû¶ó MultiUndo ¶Ç´Â MultiRedo ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù. Ãë¼Ò ¹× Àç½ÇÇà ´ë»ó ·¹ÄÚµåÀÇ À妽º´Â lParamÀ¸·Î Àü´ÞµÇ¹Ç·Î ÀÌ °ªÀ» Àμö·Î ±×´ë·Î Àü´ÞÇÏ¸é µÈ´Ù.