I am working with a Windows Forms application in C# and Visual Studio 2005.
I am showing a message box within an button click event,
string messageBoxText = "Click OK to save your changes\n";
string caption = "Confirm Changes";
MessageBoxButtons button = MessageBoxButtons.OKCancel;
//Display the MessageBox
MessageBox.Show(messageBoxText, caption, button);
MessageBoxResult result = MessageBox.Show(messageBoxText, caption, button);
The following error pops up on compilation:
Error 1 The type or namespace name 'MessageBoxResult' could not be found (are you missing a using directive or an assembly reference?)
Also, IntelliSense does not show any such thing as MessageBoxResult. I have seen this statement on MSDN. How to capture the response of the message (OK/Cancel) without using MessageBoxResult?
The MessageBoxResult Enumeration is only available on .NET 3.0+. You're using 2.0.
Use DialogResult as Walt suggested.
You could try placing
using System.Windows;
at the top of your source.
Or try DialogResult instead. That's in the System.Windows.Forms namespace, and is what Show() returns in my C# source files...
First Add Reference PresentationFramework (best from NuGet) and make using System.Windows;. Then You must use System.Windows from PresentationFramework for MessageBoxResult.
Second make using Microsoft.Win32; and pick it up for SaveFileDialog.
Related
I am trying to set up a MFC C++ App in Visual Studio 2019 such that modifies the user's text as they are typing.
Current layout is 2 radio buttons,
ID= rdbOn (set to Group = True, with Value int variable m_isOn = 1)
ID= rdbOff, m_isOn value would be = 0
and 1 Edit Control,
ID= txtInputBox, with Value CString variable m_inputString
Currently, for testing I can see how it would work for a button on click, it would take something like the following and just SetDlgItemText of the result. But that would be after they have typed, not WHILE they are typing.
void Onsomebtnclick()
{
//convert CString to String of m_inputString
//do some string manipulation
//convert back to CString
//SetDlgItemText(txtInputBox, result)
}
Update:
got EN_CHANGE to work
I was able to get EN_CHANGE working with the flag suggestion from user #GoGoWorx. However, now I just have a slight problem that the cursor is back to the beginning of the edit control txtInput.
I'm reading about using a CEdit::SetSel but don't know how to use that directly in my code. I tried
CEdit control MFC, placing cursor to end of string after SetWindowText
someDlg::someFunction()
{
//some logic stuff to get a result string
SetDlgItemText(txtInputBox, result);
//need it to set the cursor to the end
//I tried these, but it didn't recognize (expression must have class type?)
//txtInputBox.SetSel(0, -1);
//txtInputBox.SetSel(-1);
}
It sounds like you need to use the ON_EN_CHANGE message-map notification (called after the control has been updated due to typing or pasting for example)
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
ON_EN_CHANGE(IDC_EDIT_CONTROL, &CMyDialog::OnEnChangeEditControl)
END_MESSAGE_MAP()
void CMyDialog::OnEnChangeEditControl()
{
// Copy or call your Onsomebtnclick() here
}
I'm not sure what you're using for the numeric identifier for the edit control, since these are typically upper case defines - replace IDC_EDIT_CONTROL above with your define (possibly txtInputBox, but again, these are normally upper case, so I'm not sure).
Also change CMyDialog for the name of your dialog class too.
Note that we're using the ON_EN_CHANGE message-map handler here instead of the ON_EN_UPDATE, since the ON_EN_CHANGE message is sent after the control has been updated, whereas ON_EN_UPDATE is called just before it's updated.
The message-map handlers are described in the Remarks section of the CEdit control documentation: https://learn.microsoft.com/en-us/cpp/mfc/reference/cedit-class?view=msvc-160
Regarding your concern about modifying things as the user types - this should be fine, since every change (keystroke or paste from clipboard, etc.) should trigger this handler to be called, where you can change whatever you need. Just be sure that when you're updating the control, you don't trigger the ON_EN_CHANGE again and end up in a recursive 'change' loop.
You might be able to do this with some sort of flag to indicate you're the one updating the control, as opposed to the user, however it's probably better to subclass the CEdit control to do what you're wanting. There are a few examples out there of how to do this (it's not as difficult as it might sound), for example:
https://www.codeproject.com/Articles/27376/Avoiding-EN-CHANGE-notifications
I trigger an c# application by an custom action:
On failing condition, my application tells Install Shield to abort the installation process using an exit code:
static void Main(string[] args)
{
if(false)
{
Environment.ExitCode = 1;
}
}
Using this approach, Install shield´s setup displays an error message like expected:
How can I overwrite that error message by a custom text?
Reading between the lines here, it appears your custom action launches an EXE. If that is so, there is no way to do what you ask. You could show a message from your EXE before returning a non-zero exit code, but then Windows Installer would still show the Error 1722 message.
If you can instead run a function from a DLL, you have more options. Instead of returning errors, you'd be able to set properties (assuming this is an immediate mode action), and could use those properties to do further things, such as show another dialog, or exit the installation without the Error 1722 message. I don't think all the necessary configuration options are available in the limited edition - you certainly cannot edit dialogs in LE - so to do all of that, you would have to change to a more capable tool (including the Professional edition, or options from other vendors).
I've created very simple Visual Studio Add-in, ala this article by JP Booodhoo.
http://codebetter.com/jpboodhoo/2007/09/04/macro-to-aid-bdd-test-naming-style/
The addin works in debug, so if I F5 in the add in solution, and open a solution then the addin shows in the tools. However, it doesn't show when not debugging. i.e. after I've deployed the addin, closed and re-opened my solution.
Am I missing something?
In terms of deployment, I followed the deployment steps in this article and deployed it to C:\Users[your user name]\Documents\Visual Studio 2012\Addins
Alternative to macros in Visual Studio 2012
public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
{
handled = false;
if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
{
if(commandName == "KinghamExtensions.Connect.KinghamExtensions")
{
var selection = (TextSelection)(_applicationObject.ActiveDocument.Selection);
selection.SelectLine();
if (selection.Text == "") return;
var prefix = "public void ";
var index = selection.Text.IndexOf(prefix);
prefix = selection.Text.Substring(0, index) + prefix;
var description = selection.Text.Replace(prefix, String.Empty);
selection.Text = prefix + description.Replace(" ", "_").Replace("'", "_");
selection.LineDown();
selection.EndOfLine();
handled = true;
}
}
}
As I say, the code works when running the addin from vs in debug, but doesn't show in the tools menu.
Also, it doesn't show up in the keyboard options like the Git Extensions addin does meaning I can't assign a key binding.
Any thoughts?
It is hard to answer by the information you given, but at first you should check the followings:
Your AddIn should appear in the Tools>Add-in Managger...
If you set the first check box before it, than it should be loaded.
If it isn't and you get an error message, click to no, else the Studio will rename the deployed .AddIn file.
You should check if your release assembly is at the place referenced by the Assembly element like this: <Assembly>C:\Users[your user name]\Documents\Visual Studio 2012\Projects\MyAddin1\MyAddin1\bin\MyAddin1.dll</Assembly>
in the .AddIn file deployed by Visual Studio to the AddIn folder you mentioned in your question.
If it is, and the error pesrists, you should add some log to your Add-In (a Windows MessageBox will do)
and place it to the OnConnection method. The error can appear either OnConnection throws an Exception while the IDE trying to load it, or the FullClassName element in the AddIn file refers to an other name than your Connection class has.
If you get no errors and your OnConnection runs properly, then it could be an exception thrown while your code is adding your command, - if you do the same way as it is in a generated Add-In template in a try/catch block- and you need to resolve it.
I am using MsiGetProperty to get string parameter value from the installer.
And after that I am calling a managed dll and I pass the that value:
nvBufferSize = MAX_STRING;
MsiGetProperty (hMSI, "DBHMS", sDbHost, nvBufferSize);
when I pass the value of sDbHost is like this when I receive it from managed code:
srvdata-02NULNULNULNULNULNUL......
however in the interface I wrote just "srvdata-02".
With that same code it was fine with Installshield 2010, now I am upgrading it to installshield 2012.
Do you have any solution with that please?
There were some behavior changes to MsiGetProperty awhile back. Try setting nvBufferSize to MAX_SIZE instead of MAX_STRING. Also check the return code of MsiGetProperty to see if it equals ERROR_MORE_DATA or if it's returning some other code. Finally check the value of nvBufferSize to see how many bytes are needed.
BTW, if you are just trying to marshal a property over to managed code, you might want to conisder looking into Deployment Tools Framework (DTF) in Windows Installer XML (WiX). This is a very nice SDK that allows you to write managed code custom actions and package them up as if they are native Win32 libraries. InstallShield can then easily use this as an MSI DLL custom action.
DTF provides an interop library and a session object that can be used like:
Deployment Tools Foundation (DTF) Managed Custom Actions
Reasons DTF is Better
As ridiculous as it may seem, here's a working InstallScript solution for you:
nvBufferSize = MAX_STRING;
nResult = MsiGetProperty( ISMSI_HANDLE, szPropertyName, svValue, nvBufferSize );
if( nResult = ERROR_MORE_DATA ) then
MsiGetProperty( ISMSI_HANDLE, szPropertyName, svValue, nvBufferSize );
endif;
The first attempt returns the actual buffer size needed. If it is more then max string (1024?), the second call gets the whole thing.
Alternatively, I found I could assign nvBufferSize to larger value right off the bat e.g. 4096 and use that with a single call (assuming the data was no longer that limit). The double call, however, is more fool proof.
According to: https://msdn.microsoft.com/en-us/library/aa370134(v=vs.85).aspx the api function is actually designed to return the buffersize by passing an empty literal ("") instead of a string variable. InstallScript 2013 throws a compilation error at you if you try that though...
How to change font in all dialog forms in a visual c++ application?
I want to set Tahoma style.
Thanks.
You can set the font for a dialog in the resource it's created from. I believe that'll change the font on all the standard controls as well. If you have custom controls, you'll have to do additional work.
Note that if you want to have the font match the default UI font for the computer, then you can use a virtual font like "MS Shell Dlg 2" which will be mapped to Tahoma on XP, and Segoe UI on Vista+.
Replacing font in each dialog of your application would be rather tedious job.
You can employ MFC to do it for you.
Check InitInstance of your app. Look at AfxEnableControlContainer();
It is being called woithout any parameter even though AfxEnableControlContainer is declared as
void AFX_CDECL AfxEnableControlContainer(COccManager* pOccManager=NULL);
COccManager is a very interesting class and is used when has occ ( OLE custom controls) support, managing OLE container and site classes. All MFC applications are created by default with occ support. If you do not see AfxEnableControlContainer in the code generated by wizard, you do not have occ support enabled.
Anyway, instead using default occ implementation, use own and change it to change the font.
Derive class from COccManager. In this sample I call it CDlgOccManager. Override virtual PreCreateDialog:
virtual const DLGTEMPLATE* PreCreateDialog(_AFX_OCC_DIALOG_INFO* pOccDialogInfo,
const DLGTEMPLATE* pOrigTemplate);
In the implementation:
const DLGTEMPLATE* CDlgOccManager::PreCreateDialog(_AFX_OCC_DIALOG_INFO* pOccDialogInfo, const DLGTEMPLATE* pOrigTemplate)
{
CDialogTemplate RevisedTemplate(pOrigTemplate);
// here replace font for the template
RevisedTemplate.SetFont(_T("Tahoma"), -16);
return COccManager::PreCreateDialog (pOccDialogInfo, (DLGTEMPLATE*)RevisedTemplate.Detach());
}
Now you are changin font for all dialogs. Remember changing AfxEnableControlContainer call:
PROCESS_LOCAL(CDlgOccManager, pManager);
BOOL CDlgFontChangeApp::InitInstance()
{
AfxEnableControlContainer(pManager.GetData());
.
.
.
}
DO not forget to
#include "DlgOccManager.h"
For new verion of the MFC include afxdisp.h for older, occimpl.h for COccManager.
I just noticed something. It is not a blunder but it needs an explanation.
I have kept this code in my repository for a very, very, very long time.
It was a time when DLLs kept all data as global, making data available to all modules that loaded this dll. In order to force data to be stored in TLS area, I used PROCESS_LOCAL macro that expands to invoking CProcessLocal class that is still alive.
You can remove this macro and replace it with:
BOOL CDlgFontChangeApp::InitInstance()
{
CDlgOccManager* pManager = new CDlgOccManager();
AfxEnableControlContainer(pManager);
.
.
.
}