Separating taskbar icon for new form in PowerShell - winforms

When you create a windows form in PowerShell, it will group with the host console window, even if you change the icon for the form.
How do I separate the new form's taskbar icon out from the PowerShell console icon?
What happens on left, desired effect on right:
Example code:
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object System.Windows.Forms.Form
$form.Size = New-Object System.Drawing.Size(300,200)
$form.ShowInTaskbar = $true
$form.Icon = New-Object system.drawing.icon 'c:\icon.ico'
$form.Text = 'New taskbar icon plz'
$form.BringToFront()
$form.ShowDialog()
The only thing I saw that was somewhat helpful was a reference that changing the "Application ID" would separate this out, but the references are all C code.
https://msdn.microsoft.com/en-us/magazine/dd942846.aspx
Please give PowerShell answers, or if the answers include C# code or calls to other APIs, please explain how they work in PowerShell.

After cobbling together a lot of P/Invoke through C# magic from the internet, mostly from here and some from here, I ended up with this to add a type with one method you can use like [PSAppID]::SetAppIdForWindow($form.handle, "Your.AppId"):
$signature = #'
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
public class PSAppID
{
// https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
// IPropertyStore Interface
[ComImport,
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
private interface IPropertyStore
{
uint GetCount([Out] out uint cProps);
uint GetAt([In] uint iProp, out PropertyKey pkey);
uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
uint Commit();
}
// PropertyKey Structure
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct PropertyKey
{
private Guid formatId; // Unique GUID for property
private Int32 propertyId; // Property identifier (PID)
public Guid FormatId
{
get
{
return formatId;
}
}
public Int32 PropertyId
{
get
{
return propertyId;
}
}
public PropertyKey(Guid formatId, Int32 propertyId)
{
this.formatId = formatId;
this.propertyId = propertyId;
}
public PropertyKey(string formatId, Int32 propertyId)
{
this.formatId = new Guid(formatId);
this.propertyId = propertyId;
}
}
// PropVariant Class (only for string value)
[StructLayout(LayoutKind.Explicit)]
public class PropVariant : IDisposable
{
[FieldOffset(0)]
ushort valueType; // Value type
// [FieldOffset(2)]
// ushort wReserved1; // Reserved field
// [FieldOffset(4)]
// ushort wReserved2; // Reserved field
// [FieldOffset(6)]
// ushort wReserved3; // Reserved field
[FieldOffset(8)]
IntPtr ptr; // Value
// Value type (System.Runtime.InteropServices.VarEnum)
public VarEnum VarType
{
get { return (VarEnum)valueType; }
set { valueType = (ushort)value; }
}
public bool IsNullOrEmpty
{
get
{
return (valueType == (ushort)VarEnum.VT_EMPTY ||
valueType == (ushort)VarEnum.VT_NULL);
}
}
// Value (only for string value)
public string Value
{
get
{
return Marshal.PtrToStringUni(ptr);
}
}
public PropVariant()
{ }
public PropVariant(string value)
{
if (value == null)
throw new ArgumentException("Failed to set value.");
valueType = (ushort)VarEnum.VT_LPWSTR;
ptr = Marshal.StringToCoTaskMemUni(value);
}
~PropVariant()
{
Dispose();
}
public void Dispose()
{
PropVariantClear(this);
GC.SuppressFinalize(this);
}
}
[DllImport("Ole32.dll", PreserveSig = false)]
private extern static void PropVariantClear([In, Out] PropVariant pvar);
[DllImport("shell32.dll")]
private static extern int SHGetPropertyStoreForWindow(
IntPtr hwnd,
ref Guid iid /*IID_IPropertyStore*/,
[Out(), MarshalAs(UnmanagedType.Interface)] out IPropertyStore propertyStore);
public static void SetAppIdForWindow(int handle, string AppId)
{
Guid iid = new Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99");
IPropertyStore prop;
int result1 = SHGetPropertyStoreForWindow((IntPtr)handle, ref iid, out prop);
// Name = System.AppUserModel.ID
// ShellPKey = PKEY_AppUserModel_ID
// FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
// PropID = 5
// Type = String (VT_LPWSTR)
PropertyKey AppUserModelIDKey = new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);
PropVariant pv = new PropVariant(AppId);
uint result2 = prop.SetValue(ref AppUserModelIDKey, pv);
Marshal.ReleaseComObject(prop);
}
}
'#
Add-Type -TypeDefinition $signature
And then with your form:
[void][Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object System.Windows.Forms.Form
$form.Size = New-Object System.Drawing.Size(300,200)
$form.ShowInTaskbar = $true
$form.visible = $true
[PSAppID]::SetAppIdForWindow($form.Handle, "YourName.App")
It splits off into its own taskbar entry.
Raymond Chen's blog says the format of the AppID should be "CompanyName.ProductName.SubProduct.VersionInformation where the Sub­Product is optional, and the Version­Information is present only if you want different versions of your app to be treated as distinct." and no longer than 128 characters.
Raymond Chen blog entry 1
Raymond Chen blog entry 2
I think this Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99") is supposed to be a Windows Shell ID, of IPropertyStore, but I don't know how to get it without just writing it in.
Same for the AppUserModelIDKey magic GUID which comes from some Win32 propkey.h maybe?
See also:
https://github.com/microsoft/Windows-classic-samples/blob/7cbd99ac1d2b4a0beffbaba29ea63d024ceff700/Samples/Win7Samples/winui/shell/appshellintegration/AppUserModelIDWindowProperty/AppUserModelIDWindowProperty.cpp#L56
This Microsoft doc which infuriatingly handwaves away as "This is typically IID_IPropertyStore".
AppUserModelID and SystemProperties.System.AppUserModel.ID

Related

Powershell Textbox placeholder

I create my from, define my TextBoxes, and for my placeholder text I'm using the following code:
$AssetText.Add_MouseClick({ $AssetText.text = “” })
$ErrorText.Add_MouseClick({ $ErrorText.text = “” })
$IssueText.Add_MouseClick({ $IssueText = “” })
$TestTagText.Add_MouseClick({ $TestTagText.text = “” })
$TroubleshootText.Add_MouseClick({ $TroubleshootText.text = “” })
$ResolutionText.Add_MouseClick({ $ResolutionText.text = “” })
It works to remove text from the TextBox, but if I type a fair amount of text in any TextBox and then click outside of it, then come back to it, it erases the text I was working on.
Is there another function I can use that would work better than this current method? So that initially I can click the $TextBox to make the text disappear, but when writing my own text in the box wont disappear after clicking in and outside of the $TextBox?
Here is another approach on setting Placeholder text for Textbox. The approach relies on handling WM_PAINT message and has been explained and implemented here.
The difference between this approach and the other approach (sending EM_SETCUEBANNER) is this approach works for multi-line TextBox as well.
using assembly System.Windows.Forms
using namespace System.Windows.Forms
using namespace System.Drawing
$assemblies = "System.Windows.Forms", "System.Drawing"
$code = #"
using System.Drawing;
using System.Windows.Forms;
public class ExTextBox : TextBox
{
string hint;
public string Hint
{
get { return hint; }
set { hint = value; this.Invalidate(); }
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0xf)
{
if (!this.Focused && string.IsNullOrEmpty(this.Text)
&& !string.IsNullOrEmpty(this.Hint))
{
using (var g = this.CreateGraphics())
{
TextRenderer.DrawText(g, this.Hint, this.Font,
this.ClientRectangle, SystemColors.GrayText , this.BackColor,
TextFormatFlags.Top | TextFormatFlags.Left);
}
}
}
}
}
"#
#Add the SendMessage function as a static method of a class
Add-Type -ReferencedAssemblies $assemblies -TypeDefinition $code -Language CSharp
# Create an instance of MyForm.
$form = [Form] #{
ClientSize = [Point]::new(400,100);
Text = "Placeholder Sample";
}
$form.Controls.AddRange(#(
($textBox1 = [ExTextBox] #{Location = [Point]::new(10,10); Hint = "Start typing!" })
($textBox2 = [ExTextBox] #{Location = [Point]::new(10,40); Hint = "Start typing!";
MultiLine = $true; Height = 50; })
))
$null = $form.ShowDialog()
$form.Dispose()
If you would like to have placeholder in native OS way, you can send EM_SETCUEBANNER to TextBox to set the placeholder text:
using assembly System.Windows.Forms
using namespace System.Windows.Forms
using namespace System.Drawing
$code = #"
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr SendMessage(IntPtr hWnd,
int msg, IntPtr wParam, string lParam);
public const int EM_SETCUEBANER = 0x1501;
"#
$Win32Helpers = Add-Type -MemberDefinition $code -Name "Win32Helpers" -PassThru
$form = [Form] #{
ClientSize = [Point]::new(400,100);
Text = "Placeholder Text";
}
$form.Controls.AddRange(#(
($textBox1 = [TextBox] #{Location = [Point]::new(10,10) })
($textBox2 = [TextBox] #{Location = [Point]::new(10,40) })
))
$textBox1.add_HandleCreated({
$Win32Helpers::SendMessage($textBox1.Handle,$Win32Helpers::EM_SETCUEBANER`
, [IntPtr]0, "Start typing ...")
$Win32Helpers::SendMessage($textBox2.Handle,$Win32Helpers::EM_SETCUEBANER`
, [IntPtr]0, "Start typing ...")
})
$null = $form.ShowDialog()
$form.Dispose()

How to restrict the number of a blocktype used in contentarea?

I have a block type which I am using on a specific content area on a specific page. is there any way that I can validate(on page level or contentarea level) that block is not used more than once?
Here's a sample validation attribute class that should help. I am working on a "Validation Rules" nuget package that I thought could include this. I only included the "Min by object type" rule but will add more before it's released.
Class:
using EPiServer;
using EPiServer.Core;
using EPiServer.ServiceLocation;
using System;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
namespace eGandalf.Epi.Validation.Lists
{
/// <summary>
/// Detects whether the minimum required items of a specific type within a ContentArea condition has been met. Only supports items that can be loaded by IContentLoader. Supports type inheritance.
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true, Inherited = true)]
public class MinimumOfTypeAttribute : ValidationAttribute
{
public int Limit { get; }
public Type ObjectType { get; }
public MinimumOfTypeAttribute(int limit, Type t)
{
Limit = limit;
ObjectType = t;
}
public override bool IsValid(object value)
{
if (value == null && Limit > 0) return false;
var area = value as ContentArea;
if (area != null) return ValidateContentArea(area);
throw new TypeMismatchException("Minimum of type only works with ContentArea properties.");
}
private bool ValidateContentArea(ContentArea area)
{
if (area?.Items?.Count < Limit) return false;
var typeCount = 0;
foreach (var item in area.Items)
{
if (CanLoadContentByType(item.ContentLink))
{
typeCount++;
// Return as soon as the validation is true.
if (typeCount >= Limit) return true;
}
}
return false;
}
private bool CanLoadContentByType(ContentReference reference)
{
var loader = ServiceLocator.Current.GetInstance<IContentLoader>();
var loaderType = loader.GetType();
MethodInfo getMethod = loaderType.GetMethod("Get", new Type[] { typeof(ContentReference) });
MethodInfo genericGet = getMethod.MakeGenericMethod(new[] { ObjectType });
try
{
var content = genericGet.Invoke(loader, new object[] { reference });
return content != null;
}
catch (Exception ex)
{
return false;
}
}
public override string FormatErrorMessage(string name)
{
return $"ContentArea {name} must include at least {Limit} items of type {ObjectType.Name}";
}
}
}
Sample application on a content area:
[MinimumOfType(1, typeof(RssReaderBlock))]
public virtual ContentArea RelatedContentArea { get; set; }
Result in editor view when invalid (prevents publish):
Nothing built-in, but you can easily hook up to the SavingContent or PublishingContent events and validate content before it's saved/published.
Examples here and there.

Passing checkedlistbox.checked items cast as a List<BuiltInCategory> from a Form instance to a Revit class function

I am not having any issues making calls from the form instance to the Revit class. It's when I try to assign a List to the Revit class's function categoryList(), that I get a variable doesn't exist in the context error. I tried prefixing a reference to the instance of the form class "Form UF = new Form;" This doesn't work.
//The Revit Class
public Result Execute(ExternalCommandData commandData, ref string message,....)
{
User_Form UF = new User_Form(commandData);
UF.ShowDialog();
public List<BuiltInCategory> categoryList(Document doc, int intSwitch)
{
//list built in categories for built in filter_1
builtInCats_List = new List<BuiltInCategory>();
switch (intSwitch)
{
case (1):
...
case (3):
...
case (4):
{
builtInCats_List = newStateCb1;
return builtInCats_List;
}
default:
{
builtInCats_List = newStateCb1;
return builtInCats_List;
}
}
}
using Form = System.Windows.Forms.Form;
using WS = ModelAuditor_2014.WorksetSorter_2014;
using ModelAuditor_2014;
using System.Threading;
//The Form
namespace ModelAuditor_2014
{
public partial class User_Form : Form
{
//Constructor
WorksetSorter_2014 WS = new WorksetSorter_2014();
//Revit references
public Autodesk.Revit.UI.UIApplication rvtUiApp;
public Autodesk.Revit.UI.UIDocument rvtUiDoc;
public Autodesk.Revit.ApplicationServices.Application rvtApp;
//Global Variables
public List<BuiltInCategory> Filter01_CategoryList;
public List<BuiltInCategory> Filter02_CategoryList;
public int intSwitch;
public List<BuiltInCategory> newStateCb1;
public User_Form(ExternalCommandData commandData)
{
//Revit references
rvtUiApp = commandData.Application;
rvtUiDoc = rvtUiApp.ActiveUIDocument;
rvtApp = rvtUiApp.Application;
InitializeComponent();
}
public void User_Form_Load(object sender, EventArgs e)
{
//use rvtDoc = Doc
Autodesk.Revit.DB.Document rvtDoc = .....
//CheckedListBox for filter01
checkedListBox1.DataSource = WS.categoryList(rvtDoc, intSwitch = 1);
Filter01_CategoryList = new List<BuiltInCategory>();
Filter01_CategoryList = WS.RetrieveSchema(rvtDoc, false);
foreach (BuiltInCategory ChkedB1 in Filter01_CategoryList)
{
for (int i = 0; i < checkedListBox1.Items.Count; i++)
{
if (checkedListBox1.Items[i].ToString() == ChkedB1.ToString())
{
checkedListBox1.SetItemChecked(i, true);
}
}
}
public List<BuiltInCategory> returnNewStateCB1()
{
newStateCb1 = checkedListBox1.CheckedItems.Cast
<BuiltInCategory>().ToList<BuiltInCategory>();
return newStateCb1;
}
I passed the list from the win form to another public function in the revit app, I was able to access the list returned by this function.

how to update a datagridview on a Parent form from a Child Form C#

I'm quite a new C# programmer,it has been a month that ive started using C#, so far so good i might say, but im curently dealing with a simple situation , but i still dont get it to work , there is the scenario :
I've 2 forms a Parent and a Child , the parent contains a Xtragrid control and a button which opens the second form and load the textBoxes in the second form with values , the second has a button to update the values in case of any changes . but i still dont get it to work , I've the following error :
MUST DECLARE A SCALAR VARIABLE at #ID
I understood the cause of the probleme but i just cant fix it ,ive have done some researches to sort myself out but i still didnt manage to make it work
the last line
da.updatecommand.parameters.addwithvalues("ID#",ds.tables["tblLesseeYW"].Rows[LesseeYW.Position][0];
I have done it but it is not working( LesseeYW which is my binding source object but it doesnt exit in the current context nor the dataset which is understandable
: there is the code need help pleaese
// This the class ive created to retrieve all Columns from the SQl server data base
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace YoungWoman
{
public static class GetRowData
{
public static int LesseeId;
public static byte LesseePic;
public static string LesseeName;
public static string LesseeLastName;
public static string PassportNo;
public static string IDNo;
public static DateTime BirthDate;
public static string Gender;
public static string Country;
public static string City;
public static string Province;
public static string LesseePostalCode;
public static string MobileNo;
public static string HomePhoneNo;
public static string TutorName;
public static string TutorLastName;
public static string AddressTutor;
public static string AddressLessee;
public static string TutorPhoneNo;
public static string TutorEmail;
}
}
// the parent form
namespace YoungWoman
{
public partial class Lessee2 : UserControl
{
DataSet ds = new DataSet();
DataView dv ;
SqlDataAdapter daLessee = new SqlDataAdapter();
SqlDataAdapter daReservation = new SqlDataAdapter();
BindingSource LesseeYW = new BindingSource();
BindingSource ReservationCenterYW = new BindingSource();
SqlConnection conne = SqlCoonectionSEtup.GetConnection;
// the button that opens the Child Form
private void EditLesseeFrm_Click(object sender, EventArgs e)
{
Lesseefrm Lessee = new Lesseefrm(Utils.Formtype.edit, 1);
Lessee.LesseeEventHandler += new EventHandler(RefreshLesseeGrid);
GetRowData.LesseeId = Convert.ToInt32(gridView1.GetRowCellValue (gridView1.FocusedRowHandle, "LesseeId"));
GetRowData.LesseeName = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "LesseeName"));
GetRowData.LesseeLastName = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle,"LesseeLastName"));
GetRowData.PassportNo = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle,"PassportNo"));
GetRowData.Gender = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "Gender"));
GetRowData.Province = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "Province"));
GetRowData.BirthDate = Convert.ToDateTime(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "BirthDate"));
GetRowData.City = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "City"));
GetRowData.Country = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "Country"));
GetRowData.MobileNo = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "MobileNo"));
GetRowData.HomePhoneNo = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "HomePhoneNo"));
GetRowData.IDNo = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "IDNo"));
GetRowData.AddressLessee = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "AddressLessee"));
GetRowData.AddressTutor = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "AddressTutor"));
GetRowData.LesseePostalCode = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "LesseePostalCode"));
GetRowData.TutorName = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "TutorName"));
GetRowData.TutorLastName = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "TutorLastName"));
GetRowData.TutorPhoneNo = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "TutorPhoneNo"));
GetRowData.TutorEmail = Convert.ToString(gridView1.GetRowCellValue(gridView1.FocusedRowHandle, "TutorEmail"));
Lessee.ShowDialog();
}
( // Child LOad_form if form type == Edit )
if (formtype == Formtype.edit && Lesseeid > 0)
{
LesseeIdtextEdit.Enabled = false;
ClearBtnlayoutControlItem26.Visibility = DevExpress.XtraLayout.Utils.LayoutVisibility.Never;
SaveBtn.Text = "&Edit";
SaveBtn.Image = Resources.brush_16;
this.Text = string.Format(" Edit Lessee Information - YW Residence ");
LesseeIdtextEdit.Text = Convert.ToInt32(GetRowData.LesseeId).ToString();
txtName.Text = GetRowData.LesseeName;
txtLAstname.Text = GetRowData.LesseeLastName;
txtPassport.Text = GetRowData.PassportNo;
txtID.Text = GetRowData.IDNo;
GendercomboBoxEdit.SelectedItem = GetRowData.Gender;
DobdateEdit.DateTime = GetRowData.BirthDate;
CountrycomboBoxEdit.SelectedItem = GetRowData.Country;
txtProvince.Text = GetRowData.Province;
txtCity.Text = GetRowData.City;
txtPostalCode.Text = GetRowData.LesseePostalCode;
LesseememoEdit1.Text = GetRowData.AddressLessee;
txtMobile.Text = GetRowData.MobileNo;
txtHomePhone.Text = GetRowData.HomePhoneNo;
txtTutorName.Text = GetRowData.TutorName;
txttutorLastname.Text = GetRowData.TutorLastName;
tutorAddresstxt.Text = GetRowData.AddressTutor;
txtTutorMobile.Text = GetRowData.TutorPhoneNo;
txtEmail.Text = GetRowData.TutorEmail;
}
public event System.EventHandler LesseeEventHandler;
private void SaveBtn_Click(object sender, EventArgs e)
if (formtype == Formtype.edit && Lesseeid > 0)
{
MemoryStream ms = new MemoryStream();
PicBox1.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] Pic_arr = new byte[ms.Length];
ms.Position = 0;
ms.Read(Pic_arr, 0, Pic_arr.Length);
try
{
da.UpdateCommand = new SqlCommand(" UPDATE LesseeYW SET LesseePic = #image , LesseeName = #Name, LesseeLastName = #Last , PassportNo = #pass,IDNo = #Number, BirthDate =#birth ,Gender = #gender , Country =#country,LesseePostalCode = #Postal,City = #city , Province = #province,MobileNo = #Mobile,HomePhoneNo = #phone,TutorName = #tutor,TutorLastName=#Tlast,AddressTutor = #line1,AddressLessee=#line2,TutorPhoneNo = #Tphone,TutorEmail =#Temail WHERE LesseeId = #ID ", conne);
da.UpdateCommand.Parameters.AddWithValue("#image", Pic_arr);
da.UpdateCommand.Parameters.AddWithValue("#Name", txtName.Text);
da.UpdateCommand.Parameters.AddWithValue("#Last", txtLAstname.Text);
da.UpdateCommand.Parameters.AddWithValue("#pass", txtPassport.Text);
da.UpdateCommand.Parameters.AddWithValue("#Number", txtID.Text);
da.UpdateCommand.Parameters.AddWithValue("#birth", DobdateEdit.DateTime);
da.UpdateCommand.Parameters.AddWithValue("#gender", GendercomboBoxEdit.SelectedItem.ToString());
da.UpdateCommand.Parameters.AddWithValue("#country", CountrycomboBoxEdit.SelectedItem.ToString());
da.UpdateCommand.Parameters.AddWithValue("#Postal", txtPostalCode.Text);
da.UpdateCommand.Parameters.AddWithValue("#city", txtCity.Text);
da.UpdateCommand.Parameters.AddWithValue("#province", txtProvince.Text);
da.UpdateCommand.Parameters.AddWithValue("#Mobile", txtMobile.Text);
da.UpdateCommand.Parameters.AddWithValue("#phone", txtHomePhone.Text);
da.UpdateCommand.Parameters.AddWithValue("#tutor", txtTutorName.Text);
da.UpdateCommand.Parameters.AddWithValue("#Tlast", txttutorLastname.Text);
da.UpdateCommand.Parameters.AddWithValue("#line1", tutorAddresstxt.Text);
da.UpdateCommand.Parameters.AddWithValue("#line2", LesseememoEdit1.Text);
da.UpdateCommand.Parameters.AddWithValue("#Tphone", txtTutorMobile.Text);
da.UpdateCommand.Parameters.AddWithValue("#Temail", txtEmail.Text);
//da.UpdateCommand.Parameters.AddWithValue("#ID"
da.UpdateCommand.ExecuteNonQuery();
conne.Close();
MessageBox.Show("Lessee Details Updated ", "Confirmation", MessageBoxButtons.OK, MessageBoxIcon.Information);
this.Close();
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
}
}
at first you should program more objective. Dont declare all variables of your class as public static. You should make them private. To get acces you have to declare Properties.
Like this:
private string name;
public string Name
{
get {return name;}
set {name = value;}
}
if you have an ID you can easily make it read-only and noone from "outside" can modify it but everyone can read.
private int leeseId;
public int LeeseID
{
get{return leeseId;}
}
So you use "getter/setter" to offer your class properties. Further not all your variables should named leese... Just name it id,name,city,pic etc. In your form you create an Object from your class. You can name this object Leese.
private Leese leese = new Leese();
leese.id = ???
leese.name = ???
Much more readable.
da.updatecommand.parameters.addwithvalues("ID#",ds.tables["tblLesseeYW"].Rows[LesseeYW.Position][0];
You wrote "ID#" but it should be "#ID". And if you build your class as i descripe at top you can use property:
da.updatecommand.parameters.addwithvalues("#ID", leese.Id);
i hope that help you.

How to disable a WinForms TreeView node checkbox?

I need to be able to disable some of the checkboxes in a TreeView control of a WinForms application, but there's no such functionality built-in to the standard TreeView control.
I am already using the TreeView.BeforeCheck event and cancel it if the node is disabled and that works perfectly fine.
I also change the ForeColor of the disabled nodes to GrayText.
Does anyone have a simple and robust solution?
Since there's support in C++ we can resolve it using p/invoke.
Here's the setup for the p/invoke part, just make it available to the calling class.
// constants used to hide a checkbox
public const int TVIF_STATE = 0x8;
public const int TVIS_STATEIMAGEMASK = 0xF000;
public const int TV_FIRST = 0x1100;
public const int TVM_SETITEM = TV_FIRST + 63;
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam,
IntPtr lParam);
// struct used to set node properties
public struct TVITEM
{
public int mask;
public IntPtr hItem;
public int state;
public int stateMask;
[MarshalAs(UnmanagedType.LPTStr)]
public String lpszText;
public int cchTextMax;
public int iImage;
public int iSelectedImage;
public int cChildren;
public IntPtr lParam;
}
We want to determine on a node by node basis. The easiest way to do that is on the draw node event. We have to set our tree to be set as owner drawn in order for this event, so be sure to set that to something other than the default setting.
this.tree.DrawMode = TreeViewDrawMode.OwnerDrawText;
this.tree.DrawNode += new DrawTreeNodeEventHandler(tree_DrawNode);
In your tree_DrawNode function determine if the node being drawn is supposed to have a checkbox, and hide it when approriate. Then set the Default Draw property to true since we don't want to worry about drawing all the other details.
void tree_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
if (e.Node.Level == 1)
{
HideCheckBox(e.Node);
e.DrawDefault = true;
}
else
{
e.Graphics.DrawString(e.Node.Text, e.Node.TreeView.Font,
Brushes.Black, e.Node.Bounds.X, e.Node.Bounds.Y);
}
}
Lastly, the actual call to the function we defined:
private void HideCheckBox(TreeNode node)
{
TVITEM tvi = new TVITEM();
tvi.hItem = node.Handle;
tvi.mask = TVIF_STATE;
tvi.stateMask = TVIS_STATEIMAGEMASK;
tvi.state = 0;
IntPtr lparam = Marshal.AllocHGlobal(Marshal.SizeOf(tvi));
Marshal.StructureToPtr(tvi, lparam, false);
SendMessage(node.TreeView.Handle, TVM_SETITEM, IntPtr.Zero, lparam);
}
This is PowerShell version, many thanks for #sam-trost for his life-savior code!
P/invoke:
$TypeDefinition = #'
using System;
using System.Runtime.InteropServices;
namespace Win32Functions {
public class Win32TreeView {
// constants used to hide a checkbox
public const int TVIF_STATE = 0x8;
public const int TVIS_STATEIMAGEMASK = 0xF000;
public const int TV_FIRST = 0x1100;
public const int TVM_SETITEM = TV_FIRST + 63;
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
// struct used to set node properties
public struct TVITEM
{
public int mask;
public IntPtr hItem;
public int state;
public int stateMask;
[MarshalAs(UnmanagedType.LPTStr)]
public String lpszText;
public int cchTextMax;
public int iImage;
public int iSelectedImage;
public int cChildren;
public IntPtr lParam;
}
}
}
'#
Add-Type -TypeDefinition $TypeDefinition -PassThru
Event handler:
$TreeView1_DrawNode = [System.Windows.Forms.DrawTreeNodeEventHandler]{
#Event Argument: $_ = [System.Windows.Forms.DrawTreeNodeEventArgs]
if ($null -ne $_.Node) {
# P/invoke hack to hide Node CheckBox
if ($_.Node.Level -eq 0) {
Hide-NodeCheckBox($_.Node)
}
$_.DrawDefault = $true
}
}
TreeView:
$TreeView1.DrawMode = [TreeViewDrawMode]::OwnerDrawText
$TreeView1.add_DrawNode($TreeView1_DrawNode)
Function:
function Hide-NodeCheckBox([TreeNode]$node) {
# P/invoke hack to hide Node CheckBox
if ($node.TreeView.CheckBoxes) {
$tvi = [Win32Functions.Win32TreeView+TVITEM]::new()
$tvi.hItem = $node.Handle
$tvi.mask = [Win32Functions.Win32TreeView]::TVIF_STATE
$tvi.stateMask = [Win32Functions.Win32TreeView]::TVIS_STATEIMAGEMASK
$tvi.state = 0
[IntPtr]$lparam = [Marshal]::AllocHGlobal([Marshal]::SizeOf($tvi))
[Marshal]::StructureToPtr($tvi, $lparam, $false)
[Win32Functions.Win32TreeView]::SendMessage($node.TreeView.Handle, [Win32Functions.Win32TreeView]::TVM_SETITEM, [IntPtr]::Zero, $lparam)
}
}
TreeView.BeforeCheck -- register for this event, check whether the node is one where the checkboxes are allowed to be checked or not and, if it cannot be checked then you can cancel the event by setting the Cancel property on the TreeViewCancelEventArgs. That should hopefully prevent the user from checking those boxes but will not make for the best user-experience.
To remove the checkboxes for the non-checkable items, you could possibly use owner-draw to draw a solid rectangle over the check-box to remove it.
There is nothing inbuilt to do this. You can use the BeforeCheck event and cancel it for the desired nodes. In case the appearance of the checkbox matters, then you will need to place a image there to show the checkbox disabled.
This link might be of your interest.

Resources