BOOL plComponentDlg::DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: fhDlg = hDlg; IAddComponentsRecur(GetDlgItem(hDlg, IDC_TREE), (plMaxNode*)GetCOREInterface()->GetRootNode()); ICreateMenu(); ICreateRightClickMenu(); return TRUE; case WM_SIZING: IPositionControls((RECT*)lParam, wParam); return TRUE; case WM_ACTIVATE: if (LOWORD(wParam) == WA_INACTIVE) plMaxAccelerators::Enable(); else plMaxAccelerators::Disable(); return TRUE; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL) { ShowWindow(hDlg, SW_HIDE); fInterface->UnRegisterDlgWnd(hDlg); return TRUE; } else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_ATTACH) { IAttachTreeSelection(); return TRUE; } else if (HIWORD(wParam) == EN_KILLFOCUS && LOWORD(wParam) == IDC_COMMENTS) { IGetComment(); return TRUE; } // "Refresh" menu item else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == ID_REFRESH) { IRefreshTree(); return TRUE; } // "Remove unused components" menu item else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == ID_REMOVE_UNUSED) { IRemoveUnusedComps(); return TRUE; } // Item selected from 'New' menu else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) >= MENU_ID_START) { ClassDesc *desc = plComponentMgr::Inst().Get(LOWORD(wParam)-MENU_ID_START); // If this is a component type (not a category) if (desc) { // Create an object of that type and a node to reference it Object *obj = (Object*)GetCOREInterface()->CreateInstance(desc->SuperClassID(), desc->ClassID()); INode *node = GetCOREInterface()->CreateObjectNode(obj); plComponentBase *comp = (plComponentBase*)obj; node->Hide(!comp->AllowUnhide()); node->Freeze(TRUE); // Add the new component to the tree HWND hTree = GetDlgItem(hDlg, IDC_TREE); HTREEITEM item = IAddComponent(hTree, (plMaxNode*)node); TreeView_SelectItem(hTree, item); TreeView_EnsureVisible(hTree, item); } } break; case WM_NOTIFY: NMHDR *nmhdr = (NMHDR*)lParam; if (nmhdr->idFrom == IDC_TREE) { switch (nmhdr->code) { case TVN_SELCHANGED: { NMTREEVIEW *tv = (NMTREEVIEW*)lParam; IGetComment(); bool isComponent = IIsComponent(tv->itemNew.lParam); // If the new selection is a component, enable the attach button and comment field EnableWindow(GetDlgItem(hDlg, IDC_ATTACH), isComponent); SendDlgItemMessage(hDlg, IDC_COMMENTS, EM_SETREADONLY, !isComponent, 0); if (isComponent) { fCommentNode = (plMaxNode*)tv->itemNew.lParam; TSTR buf; fCommentNode->GetUserPropBuffer(buf); SetDlgItemText(hDlg, IDC_COMMENTS, buf); } else { fCommentNode = nil; SetDlgItemText(hDlg, IDC_COMMENTS, ""); } return TRUE; } break; case TVN_BEGINLABELEDIT: // If this isn't a component, don't allow the edit if (!IIsComponent(((NMTVDISPINFO*)lParam)->item.lParam)) { SetWindowLong(hDlg, DWL_MSGRESULT, TRUE); return TRUE; } // The edit box this creates kills the focus on our window, causing // accelerators to be enabled. Add an extra disable to counteract that. plMaxAccelerators::Disable(); return TRUE; // Finishing changing the name of a component case TVN_ENDLABELEDIT: { NMTVDISPINFO *di = (NMTVDISPINFO*)lParam; char* text = di->item.pszText; // If the name was changed... if (text && *text != '\0') { // Update the name of the node plMaxNode *node = IGetTreeSelection(); node->SetName(text); // Update the name in the panel too if (plComponentUtil::Instance().IsOpen()) plComponentUtil::Instance().IUpdateNodeName(node); // Make sure Max knows the file was changed SetSaveRequiredFlag(); // Return true to keep the changes SetWindowLong(hDlg, DWL_MSGRESULT, TRUE); } plMaxAccelerators::Enable(); } return TRUE; // User double-clicked. Select the objects the selected component is attached to. case NM_DBLCLK: ISelectTreeSelection(); return TRUE; case NM_RCLICK: IOpenRightClickMenu(); return TRUE; case TVN_KEYDOWN: // User pressed delete if (((NMTVKEYDOWN*)lParam)->wVKey == VK_DELETE) { IDeleteComponent(IGetTreeSelection()); return TRUE; } break; } } break; } return FALSE; }
BOOL plResponderProc::DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { static UINT dragListMsg = 0; if (dragListMsg != 0 && msg == dragListMsg) if (DragListProc(hWnd, (DRAGLISTINFO*)lParam)) return TRUE; switch (msg) { case WM_INITDIALOG: { if (!fhMenu) ICreateMenu(); fhDlg = hWnd; fhList = GetDlgItem(fhDlg, IDC_CMD_LIST); fCurState = 0; fCmdIdx = -1; fPB = pm->GetParamBlock(); fComp = (plResponderComponent*)fPB->GetOwner(); fComp->IFixOldPB(); LoadState(); // Make it so the user can drag commands to different positions dragListMsg = RegisterWindowMessage(DRAGLISTMSGSTRING); MakeDragList(GetDlgItem(hWnd, IDC_CMD_LIST)); // Setup the State Name combo HWND hStateName = GetDlgItem(hWnd, IDC_STATE_COMBO); ComboBox_LimitText(hStateName, 256); // I give up, Windows doesn't want to tell me the real font size #if 0//def CUSTOM_DRAW // TEMP HDC hDC = GetDC(hStateName); HFONT sysFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); HFONT oldFont = SelectFont(hDC, sysFont); TEXTMETRIC tm; GetTextMetrics(hDC, &tm); ComboBox_SetItemHeight(hStateName, 0, tm.tmHeight+2); DeleteFont(SelectFont(hDC, oldFont)); ReleaseDC(hStateName, hDC); #endif // Add the commands int idx = ComboBox_AddString(hStateName, "Add State"); ComboBox_SetItemData(hStateName, idx, kStateAdd); idx = ComboBox_AddString(hStateName, "Remove Current State"); ComboBox_SetItemData(hStateName, idx, kStateRemove); idx = ComboBox_AddString(hStateName, "Set Current as Default"); ComboBox_SetItemData(hStateName, idx, kStateDefault); idx = ComboBox_AddString(hStateName, "Copy Current State"); ComboBox_SetItemData(hStateName, idx, kStateCopy); HWND hSwitchCombo = GetDlgItem(hWnd, IDC_SWITCH_COMBO); int numStates = fPB->Count(kResponderStateName); for (int i = 0; i < numStates; i++) { const char *stateName = fPB->GetStr(kResponderStateName, 0, i); char buf[128]; if (!stateName || *stateName == '\0') { sprintf(buf, "State %d", i+1); stateName = buf; } ComboBox_InsertString(hStateName, i, stateName); ComboBox_AddString(hSwitchCombo, stateName); } ComboBox_SetCurSel(hStateName, fCurState); ComboBox_SetCurSel(hSwitchCombo, fStatePB->GetInt(kStateCmdSwitch)); } return TRUE; #ifdef CUSTOM_DRAW case WM_DRAWITEM: if (wParam == IDC_STATE_COMBO) { IDrawComboItem((DRAWITEMSTRUCT*)lParam); return TRUE; } break; #endif case WM_SETCURSOR: { if (HIWORD(lParam) == WM_RBUTTONDOWN && HWND(wParam) == GetDlgItem(hWnd, IDC_CMD_LIST)) { ICmdRightClick(HWND(wParam)); return TRUE; } } break; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED) { if (LOWORD(wParam) == IDC_ADD_ACTIVATOR) { // Adding an activator. Set it and refresh the UI to show it in our list. plPick::Activator(fPB, kResponderActivators, false); pm->Invalidate(kResponderActivators); return TRUE; } else if (LOWORD(wParam) == IDC_ADD_CMD) { AddCommand(); return TRUE; } // Remove the currently selected condition else if (LOWORD(wParam) == IDC_REMOVE_CMD) { RemoveCurCommand(); return TRUE; } } else if (HIWORD(wParam) == LBN_SELCHANGE && LOWORD(wParam) == IDC_CMD_LIST) { ICreateCmdRollups(); return TRUE; } else if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_SWITCH_COMBO) { int sel = ComboBox_GetCurSel((HWND)lParam); if (sel != CB_ERR) fStatePB->SetValue(kStateCmdSwitch, 0, sel); } else if (LOWORD(wParam) == IDC_STATE_COMBO) { HWND hCombo = (HWND)lParam; int code = HIWORD(wParam); // Disable accelerators when the combo has focus, so that new names can be typed in if (code == CBN_SETFOCUS) { plMaxAccelerators::Disable(); return TRUE; } else if (code == CBN_KILLFOCUS) { plMaxAccelerators::Enable(); return TRUE; } // State name changed, save it in the PB else if (code == CBN_EDITCHANGE) { char buf[256]; ComboBox_GetText(hCombo, buf, sizeof(buf)); const char *curName = fPB->GetStr(kResponderStateName, 0, fCurState); if (!curName || strcmp(buf, curName)) { HWND hSwitch = GetDlgItem(hWnd, IDC_SWITCH_COMBO); int sel = ComboBox_GetCurSel(hSwitch); ComboBox_DeleteString(hSwitch, fCurState); ComboBox_InsertString(hSwitch, fCurState, buf); ComboBox_SetCurSel(hSwitch, sel); fPB->SetValue(kResponderStateName, 0, buf, fCurState); ComboBox_DeleteString(hCombo, fCurState); ComboBox_InsertString(hCombo, fCurState, buf); // ComboBox_SetCurSel(hCombo, fCurState); } return TRUE; } else if (code == CBN_SELCHANGE) { int sel = ComboBox_GetCurSel(hCombo); int type = ComboBox_GetItemData(hCombo, sel); if (type == kStateAdd) { IParamBlock2 *pb = CreateParameterBlock2(&gStateBlock, nil); fCurState = AddState(pb); fCmdIdx = -1; } else if (type == kStateRemove) { int count = fPB->Count(kResponderState); // Don't let the user remove the last state if (count == 1) { hsMessageBox("You must have at least one state.", "Error", hsMessageBoxNormal); ComboBox_SetCurSel(hCombo, fCurState); return TRUE; } // Verify that the user really wants to delete the state else { int ret = hsMessageBox("Are you sure you want to remove this state?", "Verify Remove", hsMessageBoxYesNo); if (ret == hsMBoxNo) { ComboBox_SetCurSel(hCombo, fCurState); return TRUE; } } fPB->Delete(kResponderState, fCurState, 1); fPB->Delete(kResponderStateName, fCurState, 1); ComboBox_DeleteString(hCombo, fCurState); ComboBox_SetCurSel(hCombo, 0); HWND hSwitch = GetDlgItem(hWnd, IDC_SWITCH_COMBO); ComboBox_DeleteString(hSwitch, fCurState); // If the deleted state was the default, set the default to the first int defState = fPB->GetInt(kResponderStateDef); if (fCurState == defState) fPB->SetValue(kResponderStateDef, 0, 0); else if (fCurState < defState) fPB->SetValue(kResponderStateDef, 0, defState-1); // Patch up the switch commands for (int i = fCurState; i < fPB->Count(kResponderState); i++) { IParamBlock2 *pb = (IParamBlock2*)fPB->GetReferenceTarget(kResponderState, 0, i); int switchState = pb->GetInt(kStateCmdSwitch); // TODO: might want to warn about this if (switchState == fCurState) pb->SetValue(kStateCmdSwitch, 0, 0); else if (switchState > fCurState) pb->SetValue(kStateCmdSwitch, 0, switchState-1); } fCurState = 0; fCmdIdx = -1; } else if (type == kStateDefault) { // Set the current state as the default fPB->SetValue(kResponderStateDef, 0, fCurState); ComboBox_SetCurSel(hCombo, fCurState); } else if (type == kStateCopy) { // Clone the state PB IParamBlock2 *origPB = (IParamBlock2*)fPB->GetReferenceTarget(kResponderState, 0, fCurState); IParamBlock2 *copyPB = (IParamBlock2*)origPB->Clone(gMyRemapDir); fCurState = AddState(copyPB); fCmdIdx = -1; } else { fCurState = sel; fCmdIdx = -1; } LoadState(); return TRUE; } } } return FALSE; }