How to add my own right click menu? - visual-studio-2010

How to add my right click menus in SSMS 2008R2\2012 Object Explorer?
I researched this topic.
I do this way:
private void Provider_SelectionChanged(object sender, NodesChangedEventArgs args)
{
INodeInformation[] nodes;
int nodeCount;
objectExplorer.GetSelectedNodes(out nodeCount, out nodes);
INodeInformation node = (nodeCount > 0 ? nodes[0] : null);
if (_databaseMenu == null &&
_databaseRegex.IsMatch(node.Context))
{
_databaseMenu = (HierarchyObject)node.GetService(typeof(IMenuHandler));
_databaseMenu.AddChild(string.Empty, new MenuItem());
}
}
BUT the problem is: if I do left click on database and then right click - I see my menu, ok. If I expand the object tree via (+) and then immediately right click on database - I do not see my menu.
I understand why it is but how to solve this problem?

I spent a considerable amount of time working on this same issue for my own SSMS add-in. What I came up with is a dirty hack, but it was the only way I could find to get it working reliably.
You use SendKeys.SendWait to issue SHIFT + F10, which is the shortcut to open the context menu, and you do it twice, since a single issuance will toggle the menu's state (visible to not or vice versa). The UI will stop responding and eventually throw if you use Send, so be sure to use SendWait.
There will be a slight delay on left click or flicker of the menu on right click. And, of course, this won't work if the user has altered that shortcut (or has defined external, superseding macros), but a quick glance through the SSMS options doesn't reveal any way to change the context menu shortcut.
private void Provider_SelectionChanged(object sender, NodesChangedEventArgs args)
{
INodeInformation[] nodes;
int nodeCount;
objectExplorer.GetSelectedNodes(out nodeCount, out nodes);
INodeInformation node = (nodeCount > 0 ? nodes[0] : null);
if (_databaseMenu == null &&
_databaseRegex.IsMatch(node.Context))
{
_databaseMenu = (HierarchyObject)node.GetService(typeof(IMenuHandler));
_databaseMenu.AddChild(string.Empty, new MenuItem());
SendKeys.SendWait("+({F10})")
SendKeys.SendWait("+({F10})")
}
}

Related

ContextMenuStrip disappears after a quarter second display

Well, I'm back. I solved the ListBox problem by using a ContextMenuStrip — or so I thought!
It comes in perfect, then in a quarter second, two things happen: it disappears, and the TreeNode unselects.
But for that quarter second, it looks perfect!
The way that progresses is, I step through the lines of code on the right of the screenshot, 5 lines, then one more F11, and it appears for a 1/4 second, and the TreeNode UNSELECTS.
But here's another interesting thing:
In Design Mode, I clicked the reference to contextMenuStrip1 in the dialog bar beneath the Form, and it appears in the place I dropped it.
Then a click on the TreeView (white as I suppose you know) and it disappears.
Ah, but then I take the mouse and pull the TreeView over to the right, again click the reference below, again the ContextMenuStrip appears, then I click the TreeView, and AGAIN it disappears!
What am I missing, dear friends? Something to do with the focus?
Much obliged for any help.
Got it! I found that responding to Closing could be stopped for study with a break point. Then poked around in the Properties, and tried a few things. Then ultimately googled and found the answer at
Do not close ContextMenuStrip on selection of certain items. I added AppFocusChange as not a reason to close.
So far, I'm now able to click the members and select them. Progress!
private void contextMenuStrip1_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
if (e.CloseReason == ToolStripDropDownCloseReason.AppClicked ||
e.CloseReason == ToolStripDropDownCloseReason.AppFocusChange)
e.Cancel = true;
}
if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked)
{
for (int i = 0; i < 4; i++)
{
if (contextMenuStrip1.Items[i].Selected == true)
{
bool res = DoChoice(i);
if (res == true) e.Cancel = false;
}
}
}
Then, at DoChoice, I'll invoke the Add or Edit accordingly, and always returna Close to the strip.

Unity show pop up if the player doesn't move for 5 seconds

I have a task on Unity 3d that if the player doesn't move for 5 seconds, a pop-up shows on the center of the screen and if the player moves, the pop-up disappears. How can I write the logic for this task please ?
Thanks
Here is code that will check the mouse position of the user and see if it has moved in the last 5 seconds. If it has not, then the popup window will show up. If it's hard to read here with the comments (I kind of think it is) copy and paste this code into Visual Studio so the colors will help distinguish code from comments.
[SerializeField] GameObject popupWindow = null;
float totTime;
float timeBeforePause = 5f;
Vector3 updatedMousePosition;
private void Update()
{
// Add the time delta between frames to the totTime var
totTime += Time.deltaTime;
// Check to see if the current mouse position input is equivalent to updateMousePosition from the previous update
// If they are equivalent, this means that the user hasn't moved the mouse
if (Input.mousePosition == updatedMousePosition)
{
// Since the user hasn't moved the mouse, check to see if the total Time is greater than the timeBeforePause
if (totTime >= timeBeforePause)
{
// Set the popup window to true in order to show the window (instantiate instead it if if doesn't exist already)
popupWindow.SetActive(true);
}
}
// If the user has moved the mouse, set the totTime back to 0 in order to restart the totTime tracking variable
else
{
totTime = 0;
}
// Check to see if the popup window is visible (active)
if (popupWindow.activeSelf == true)
{
// Check to see if the user has pressed the Esc button
if (Input.GetKeyDown(KeyCode.Escape))
{
// Hide the window
popupWindow.SetActive(false);
}
}
// Update the updatedMousePosition before the next frame/update loop executes
updatedMousePosition = Input.mousePosition;
}
If you want to track different user input (key presses) you can use a similar method. Also you will have to implement some sort of button on the popup window that will allow the user to exit out from the popup window once they return. Hope this helps!

C++/CLI multiple buttons maintaining variable value

OK let me explain my problem.
I'm working on a program where I have a button. Clicking it causes the number "1" to appear, then, after that, any further clicks will increment that value until it reaches the value of "9". (It's a string). I wrote this code which declares an int variable to 0 (Yes, this was a mistake but let me continue) then increment it and parse it to string and show it on the button text(This is the code that executes on button click):
private: System::Void a0_Click(System::Object^ sender, System::EventArgs^ e) {
int i = 0;
i++;
a0->Text = i.ToString();
}
However, as you can suspect, I did the foolishness of declaring i with 0 for each button press, so the result was that 1 was the only value showing on the button. The next thing I tried doing, was declaring i as global variable with the value of 0. However, I came to another problem. I have 82 buttons of that kind, and I'm going for the easiest sollution I can find, so sharing the i variable seemed logical,
The next problem was that if I pressed 5 times the first button, the number displayed on it would be "5" however if I pressed another button, the value wouldn't be "1" by default, it would be "6" (The value of the first button incremented by one). Basically it would inherit the value of the first.
Now I'm at a dead end. I have no idea what to do. I tried using i and i2 but I was just chasing my own tail. Is there a very easy solution to this? Keep in mind I've got 82 buttons (Yes I know it's alot) which are by default 0. When I click each one I need it to increment by one, starting from 0. Any ideas?
Notes: OS is Windows XP, IDE is Visual Studio 2010m using windows forms app, C++/CLI. If I forgot to mention anything post in comments and I'll add it.
You can inspect sender to find out what button was clicked.
void anybutton_Click(System::Object^ sender, System::EventArgs^)
{
Button^ btn = dynamic_cast<Button^>(sender); // or safe_cast
int i;
if (System::Int32::TryParse(btn->Text, i)) {
i++;
btn->Text = i.ToString();
}
}

Selected Item in ListBox gray out after returning from other page

I have two pages : P1 and P2.
In P1,
a) Loading data from IsolatedStorage and DataBinding to listBox1 take place in Button click event in P1.
b) user select an item and be navigated to P2
example : user select CarModel_1
in P2:
user press Back Key in P2 to return to P1.
The problem :
When returnning from P2, the Selected Item in ListBox1 becomes gray out or Not clickable to go to P2.
example : CarModel_1 becomes gray out or Not clickable.
The rest is clickable.
Appreciate your help on this.
Thanks
One common way around this problem is to set SelectedIndex = -1 for the listbox.
You can see this in action if you create a default Databound project.
This is the code that is produced.
private void MainListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// If selected index is -1 (no selection) do nothing
if (MainListBox.SelectedIndex == -1)
return;
// Navigate to the new page
NavigationService.Navigate(new Uri("/DetailsPage.xaml?selectedItem=" + MainListBox.SelectedIndex, UriKind.Relative));
// Reset selected index to -1 (no selection)
MainListBox.SelectedIndex = -1;
}
The alternative to this is to implement the gesture service as outlined in this question.
Is there a click behavior for a list?

How to use a CTabCtrl in a MFC dialog based application?

I need to do something which i expected to be was simple - create a tab control which has 2 tabs, implying 2 modes of operation for my app. When user clicks on Tab1, he'll be presented with some buttons and textboxes, and when he clicks Tab2, some other input method. I noticed that there was a CTabCtrl class thats used in MFC to add tabs.
However, once I added the tab ctrl using the UI designer, I couldn't specify how many tabs there'll be using property window. Searching on the net, I found some examples but all of them required you to derive from CtabCtrl , create 2 or more child dialogs etc and to write your own custom class. My question is, since I want to do something so basic, why couldn't I do it using the familiar Add Event handler/Add member variable wizard and then handle everything else inside my app's class ? Surely, the default CTabCtrl class can do something useful without needing to derive from it ?
Forget about CTabCtrl and use CMFCTabCtrl which is much easier to work with (this is assuming you are working on VS2008 SP1).
Failing that, you seem to misunderstand how the tab control works. It only provides the 'tab strip' at the top and sends messages when the user clicks on another one. It doesn't provide you with 'tab canvases' on which you can put controls. Showing and hiding the controls on the tab is something that the programmer needs to take care of. The resource editor provides little support there. Like Stewart says, the most common way of working is to have child dialogs in your tab and hide all of them except the one of the current tab.
You don't need to derive from CTabCtrl, you can also implement the switching behavior in the window that is the parent of the CTabCtrl.
The MFC tab control is a pretty thin wrapper over the win32 tab control, which works in pretty much the way you describe. It is a window, which provides switching between child windows using tabs. As it happens, in straight win32 this is the most useful way for it to work. If you want to do something more sophisticated than switching between individual windows, you do this by using child dialogs. MFC doesn't do a great deal to help you, but deriving from CTabCtrl and using child dialogs is really not very difficult to do, although if you're used to the way WinForms does tab controls it does seem unnecessary.
If you want the tab control at the root of the dialog, with no other controls along side it, you might want to look at CPropertySheet (http://msdn.microsoft.com/en-us/library/d3fkt014(VS.80).aspx) which is probably simpler to use. Unless you want to use any of the wizard functionality you don't even need to derive from it - you just create a couple of child dialog classes, then in the place where you want to create the property sheet, make an object, add the pages to it and invoke it.
The approach I took with an MFC dialog that contained a CTabCtrl was to derive a small class to manage the tab control and used dialog templates to create the actual tab window contents.
This is still being worked on so the source code is not very clean however here are some pieces. For instance CTabCtrlDialog needs constructor and destructor in order to release object which may have been created.
In the resource file I have a dialog template with a tab control followed by three dialog templates for each of the different tab content windows inserted into the tab control. While the dialog displaying the tab control has the WS_POPUP style, the dialog templates for the tab windows that are inserted into the tab control have a WS_CHILD style instead. This change makes the tab windows child windows so that when the dialog is moved, everything stays lined up properly with no further effort on my part.
In my case the tab windows which are inserted into the tab control display a set of check boxes to indicate various operational parameters. Using a dialog template approach makes it very easy to create the necessary tab window content.
I derive a class from CTabCtrl that extends the standard MFC class with an additional method for inserting into the tab control a tab window based on a specified dialog template id. Since this is just a single dialog, I just put this class into the same files, .h and .cpp, as the dialog components themselves.
class CTabCtrlDialog : public CTabCtrl
{
public:
void InsertItemDialogTemplate (UINT nIDTemplate, int nItem, TCITEM* pTabCtrlItem);
public:
struct {
UINT nIDTemplate;
CDialog *pDialog;
} m_pDialogData[10];
};
The method InsertItemDialogTemplate() looks like:
/*
* InsertItemDialogTemplate ()
*
* Insert into a tab control a tab pane based on the specified dialog template. The
* dialog template describes what the tab pane looks like so far as controls, etc.
*
* NOTE: The STYLE description must be WS_CHILD and not WS_POPUP. Also the dialog
* needs to have as its top coordinate some distance in pixels so that the
* various tab descriptions are visible. For instance an example dialog
* template in the resource file may look like:
* IDD_CASHIER_TAB_ONE DIALOGEX 0, 10, 178, 113
* STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
* FONT 8, "MS Shell Dlg", 400, 0, 0x1
* BEGIN
* LTEXT "Dialog Tab one",IDC_STATIC,6,44,90,17
* END
*
**/
void CTabCtrlDialog::InsertItemDialogTemplate (UINT nIDTemplate, int nItem, TCITEM* pTabCtrlItem)
{
InsertItem (nItem, pTabCtrlItem);
m_pDialogData[nItem].nIDTemplate = nIDTemplate;
m_pDialogData[nItem].pDialog = new CDialog ();
m_pDialogData[nItem].pDialog->Create (nIDTemplate, this);
m_pDialogData[nItem].pDialog->ShowWindow (FALSE);
}
For handling tab selection which displays the various tabs I have the following message map and then the two event handlers in the dialog.
BEGIN_MESSAGE_MAP(CDiaCashierEdit, CDialog)
ON_NOTIFY(TCN_SELCHANGE, IDC_TAB_CASHIER_EDIT_STATUS, &CDiaCashierEdit::OnTcnSelchangeTabCashierEditStatus)
ON_NOTIFY(TCN_SELCHANGING, IDC_TAB_CASHIER_EDIT_STATUS, &CDiaCashierEdit::OnTcnSelchangingTabCashierEditStatus)
END_MESSAGE_MAP()
void CDiaCashierEdit::OnTcnSelchangeTabCashierEditStatus(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: Add your control notification handler code here
*pResult = 0;
int i = TabCtrl_GetCurSel(pNMHDR->hwndFrom);
m_TabCtrl.m_pDialogData[i + 1].pDialog->ShowWindow (TRUE);
}
void CDiaCashierEdit::OnTcnSelchangingTabCashierEditStatus(NMHDR *pNMHDR, LRESULT *pResult)
{
// TODO: Add your control notification handler code here
*pResult = 0;
int i = TabCtrl_GetCurSel(pNMHDR->hwndFrom);
m_TabCtrl.m_pDialogData[i + 1].pDialog->ShowWindow (FALSE);
}
In the DoDataExchange() method of the dialog I have the following which creates first the tab control and then creates each of the tab windows and inserts them into the tab control.
void CDiaCashierEdit::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT_CASHIER_NAME, m_CashierName);
DDX_Control(pDX, IDC_EDIT_CASHIER_SUPNO, m_SupervisorId);
DDX_Control(pDX, IDC_EDIT_CASHIER_TEAMNO, m_TeamNumber);
DDX_Control(pDX, IDC_EDIT_CASHIER_GCSTART, m_GuestCheckStart);
DDX_Control(pDX, IDC_EDIT_CASHIER_GCEND, m_GuestCheckEnd);
DDX_Control(pDX, IDC_TAB_CASHIER_EDIT_STATUS, m_TabCtrl);
if (pDX->m_bSaveAndValidate) {
m_CashierName.GetWindowText (m_paraCashier.auchCashierName, 20);
m_paraCashier.usSupervisorID = m_SupervisorId.GetWindowTextAsInt();
m_paraCashier.uchTeamNo = m_TeamNumber.GetWindowTextAsInt();
m_paraCashier.usGstCheckStartNo = m_GuestCheckStart.GetWindowTextAsInt();
m_paraCashier.usGstCheckEndNo = m_GuestCheckEnd.GetWindowTextAsInt();
for (int i = 0; i < sizeof(m_TabItemOneStatus)/sizeof(m_TabItemOneStatus[0]); i++) {
int iTab = m_TabItemOneStatus[i].sTabItem;
int iDlg = m_TabItemOneStatus[i].iDlgItem;
int iOffset = m_TabItemOneStatus[i].sOffset;
CButton *p = (CButton *) m_TabCtrl.m_pDialogData[iTab].pDialog->GetDlgItem(iDlg);
if (p->GetCheck()) {
m_paraCashier.fbCashierStatus[iOffset] |= m_TabItemOneStatus[i].uchBit;
} else {
m_paraCashier.fbCashierStatus[iOffset] &= ~(m_TabItemOneStatus[i].uchBit);
}
}
} else {
m_CashierName.SetWindowText(m_paraCashier.auchCashierName);
m_SupervisorId.SetWindowTextAsInt (m_paraCashier.usSupervisorID);
m_TeamNumber.SetWindowTextAsInt (m_paraCashier.uchTeamNo);
m_GuestCheckStart.SetWindowTextAsInt (m_paraCashier.usGstCheckStartNo);
m_GuestCheckEnd.SetWindowTextAsInt (m_paraCashier.usGstCheckEndNo);
m_TabCtrl.InsertItemDialogTemplate (IDD_CASHIER_TAB_ONE, 1, &m_TabItemOne);
m_TabCtrl.InsertItemDialogTemplate (IDD_CASHIER_TAB_TWO, 2, &m_TabItemTwo);
m_TabCtrl.InsertItemDialogTemplate (IDD_CASHIER_TAB_THREE, 3, &m_TabItemThree);
for (int i = 0; i < sizeof(m_TabItemOneStatus)/sizeof(m_TabItemOneStatus[0]); i++) {
int iTab = m_TabItemOneStatus[i].sTabItem;
int iDlg = m_TabItemOneStatus[i].iDlgItem;
int iOffset = m_TabItemOneStatus[i].sOffset;
CButton *p = (CButton *) m_TabCtrl.m_pDialogData[iTab].pDialog->GetDlgItem(iDlg);
if (m_paraCashier.fbCashierStatus[iOffset] & m_TabItemOneStatus[i].uchBit) {
p->SetCheck (1);
} else {
p->SetCheck (0);
}
}
m_TabCtrl.m_pDialogData[1].pDialog->ShowWindow (TRUE);
}
}

Resources