저희 회사 기술자에게 확인한 내용입니다.
RegisterWindowMessage를 사용한 경우가 문제입니다.
이 함수를 사용해서 메시지를 등록하면
해당 메시지가 발생할 때 모든 프로세스에 그 메시지를 전달한다고 합니다.
그래서 RegisterWindowMessage를 사용하지 않는 경우 오동작할 가능성이 없고
RegisterWindowMessage를 사용하는 경우 WndProc를 사용해서 처리하라는 의미로 보입니다.
(그러나.. RegisterWindowMessage를 사용하더라도 WndProc 사용에는 문제가 있으니
RegisterWindowMessage 사용을 검토해 보시기 바랍니다)
BEGIN_MESSAGE_MAP과 WndProc 사용은 별 관계없고 문제도 없습니다.
그리고 메시지값에 (WM_USER+1) 이런 식으로 적으셨는데
식별이 곤란하게 되어 나중에 버그의 원인이 되기도 합니다.
#define msg_MyMessage WM_USER+1 <- 이런 식으로 정의해서 쓰세요.
또..
MS의 Common Control의 내부 메시지 맵을 보면 탭 처리 메시지 등이 WM_USER+1 식으로 정의되었답니다.
그래서 WM_USER+1 이라는 메시지값을 사용할 경우 그 담당자분이 말씀하신대로 오동작할 가능성이 있습니다.
WM_USER+100 정도부터 시작하는 값을 정의해 보세요.
공윤경 님이 쓰신 글 :
: 메세지에서 WM_USER+1을 사용하고있지만, 문제가 있으므로 수정해주세요
: (헤더의 BEGINMESSAGE_MAP과 Post Messge등)
: 이것은 고정의 값을정하였을때 사용하는것이므로 , 같은 식의 코딩을 한 다른 소프트웨어가 있으면,
: 오동작 하는 원인이 됩니다.
: BEGIN_MESSAGE_MAP을 그만사용해주세요.
: WndProc을 사용해 처리해주세요.
: RegisterWindowMessage를 사용하는 부분도 참고해주세요
: ---------------------------------------------------------------------------------------
: 금요일 담당자로부터 받은 메세지 입니다.
: 워낙 기본지식이 없는지라..
: 이 밑에서 이것저것 찾아보니 WM_USER가 선언할수있다는것
: 또 MESSAGE_MAP의 설명이 나와있는데요...
: 저는 이것이 도대체 어떤식으로 수정하라는것인지를 모르겠네요.
: WndProc이란것이 메세지를 중간에 가로채는 역할을 하나요?
: 프로그램이 시작되어서 계속 무한루프를 도는듯 하는데...
:
: BEGIN_MESSAGE_MAP
: MESSAGE_HANDLER((WM_USER+1), TMessage, Interrupt)
: END_MESSAGE_MAP(TForm)
: 제가 갖고있는 소스의 헤더파일에는 이렇게 적혀 있구요
:
:
: void TFormList::Interrupt(TMessage &msg)
: {
: unsigned short reg;
: AnsiString data;
: if(msg.LParam < 0){
: MsgDlg(14, FormMain->thCom->gErr); // "通信エラー"
: } else {
: FormMain->thCom->GetData(msg.WParam, ®, &data);
: for(int i=1;i<ListScrn->RowCount;i++){
: if(ListScrn->Cells[1][i].ToInt() == reg){
: ListScrn->Cells[0][i] = "";
: ListScrn->Cells[3][i] = data;
: FormMain->SetData(reg, data); //gDataへ格納
: ListScrn->Row = i;
: SelRow = i;
: ListScrn->Refresh();
: break;
: }
: }
: }
: }
: 세개정도의 화일에 각기 다른 인터럽트 함수가 정의되어있구요
:
: 메세지 맵이라는것이
: PostMessage로부터 WM_USER+1가 들어오면 메세지를 인터럽트함수로 넘겨준다는걸 선언한건가요?
:
:
:
: BOOL ComTxRx::txrx_com(void)
: {
: int ret;
: MSG_TX tmp;
:
: while(rp != tp){ // 送信バッファにデータが存在する間繰り返す
: if(rp < (BUFFER_MAX - 1)) rp++;
: else rp = 0;
: if(hCom != NULL){
: memcpy(&tmp, &gTx[rp], sizeof(MSG_TX));
: //int BeforeTime = GetTickCount();
: for(int retry=5;retry>0;retry--){
: gErrSub = "(Reg:0x"+IntToHex(tmp.reg,4);
: ret = transfer_msg(&tmp); // 送信
: if(ret < 0){
: gErr = "Send error " + gErrSub;
: retry = 0;
: } else {
: ret = receive_msg(&gRx[rp]); // 受信
: switch(ret){ /* 返信待ち */
: case ST_CONTINUE:/* 継続中 */
: make_msg_c(&tmp);
: Sleep(200);
: retry--;
: gErr = "Recv error(no response)";
: break;
: case ST_COMPLETE:/* 正常終了 */
: if(gTx[rp].func == FC_WRITE){
: /* 受信データを統一する */
: memcpy(&gRx[rp].reg, &gTx[rp].reg, sizeof(short) * (MSG_DATA_MAX - 1));
: gRx[rp].status = ST_COMPLETE;
: }
: gRx[rp].func = gTx[rp].func;
: retry = 0;
: gErr = "";
: break;
: default:/*異常終了*/
: retry = 0;
: gErr = "Recv error("+IntToStr(ret)+")" + gErrSub;
: // uMsg = ret;
: }
: }
: }
: //gTime = GetTickCount() - BeforeTime;
: } else {
: gErr = "Port cannot be used";
: ret = (-1);
: }
:
: if(ret == ST_COMPLETE){
: PostMessage(gForm[rp]->Handle, WM_USER+1, rp, gId[rp]);
: } else {
: PostMessage(gForm[rp]->Handle, WM_USER+1, rp, (-1) * gId[rp]);
: rp = tp; //エラーが発生した場合、以降のメッセージを破棄(継続中エラーの場合が心配)
: }
:
: if(gAbort){
: gLog="Abort.";
: rp = tp;
: gAbort = false;
: }
: }
: gBusy = false;
:
: return(true);
: }
: (ComTxRx.cpp)
:
: postMessage가 불려지는 부분은 이곳이랍니다.
:
: WndProc은 메인화일 한곳에만 써주면 되는것인가요?
: WM_USER가 사용자가 지정하는것이고 담당자 말에 의하면 다른프로그램에서도 같은방법으로 쓰면 오동작을 하는 원인이 된다고 하는데...그렇다면 다른것역시 마찬가지 아닌가요?
: 사용하지말라고 했으면 WndProc을 사용하려면 PostMessage역시 사용하지말고 다른것을 이용해야 하는것인지...
: RegisterWindowMessage은 제일처음 실행할때
:
: 글구... PostMessage를 호출하는건 메인이 아니라 다른화일이거든요
: 그래도 WndProc은 메인폼에 넣는건가요?
:
: 너무너무 답답하게 질문을 했는데 정말..제가 설명할수있는게 여기까지거든요 ㅠㅠ
: 죄송합니다.
: 그리고 부탁드려요.
|