先来看一下ArcMap的符号选择器:
ArcMap的符号选择器都提供了符号的预览图,另一个预览图的位置是在按钮上,比如设置MapGrid的格网交点符号和格网线符号。
本文给出生成这里的符号预览图的代码。
方法1:通过ISymbologyStyleClass的Preview方法生成预览图
private string routin_ReadRegistry(string sKey)
{
Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(sKey, true);
if (rk == null) return "";
return (string)rk.GetValue("InstallDir");
}
public void LoadStyleGalleryItems()
{
string sInstall = routin_ReadRegistry("SOFTWARE\\ESRI\\CoreRuntime");
if (sInstall == "")
{
return;
}
ISymbologyControl pSymbologyControl = new SymbologyControlClass();
pSymbologyControl.LoadStyleFile(sInstall + "\\Styles\\ESRI.ServerStyle");
m_pSymbologyStyleClass = pSymbologyControl.GetStyleClass(esriSymbologyStyleClass.esriStyleClassScaleBars);
//Clean items in ImageComboBox and images in ImageCollection.
this.imageComboBoxEdit1.Properties.Items.Clear();
this.imageCollection1.Images.Clear();
int nWidth, nHeight;
nWidth = this.imageCollection1.ImageSize.Width;
nHeight = this.imageCollection1.ImageSize.Height;
Image pImage = null;
//Load StyleGalleryItems into he ImageComboBox's drop down list.
IStyleGalleryItem pStyleGalleryItem = null;
IPictureDisp pPicture = null;
for (int i = 0; i < m_pSymbologyStyleClass.get_ItemCount(m_pSymbologyStyleClass.StyleCategory); i++)
{
pStyleGalleryItem = m_pSymbologyStyleClass.GetItem(i);
pPicture = m_pSymbologyStyleClass.PreviewItem(pStyleGalleryItem, nWidth, nHeight);
pImage = System.Drawing.Image.FromHbitmap(new IntPtr(pPicture.Handle));
AddItem(pStyleGalleryItem.Name, pImage, pStyleGalleryItem, i);
}
this.imageComboBoxEdit1.SelectedIndex = 0;
}
private void AddItem(string sDescription, Image pImage, IStyleGalleryItem pStyleGalleryItem, int nImageIndex)
{
this.imageComboBoxEdit1.Properties.Items.Add(new ImageComboBoxItem(sDescription, pStyleGalleryItem, nImageIndex));
this.imageCollection1.Images.Add(pImage);
}
//其中m_pSymbologyStyleClass是ISymbologyStyleClass的实例。
//上面的代码演示如何使用ISymbologyControl接口在下拉列表控件中加载符号集,其中包含生成预览图的代码,对于符号选择器,使用SymbologyControl,可以直接参考AE范例里的符号选择器的例子,下面是符号选择器里更为精简的代码:
protected void PreviewImage()
{
ISymbologyStyleClass pSymbologyStyleClass = wndSymbologyControl.GetStyleClass(wndSymbologyControl.StyleClass);
IPictureDisp pPicture = pSymbologyStyleClass.PreviewItem(m_StyleGalleryItem, wndPictureEdit.Width - 10, wndPictureEdit.Height - 10);
Image pImage = Image.FromHbitmap(new IntPtr(pPicture.Handle));
wndPictureEdit.Image = pImage;
}
protected void LoadStyleCalss(esriSymbologyStyleClass styleClass)
{
string sInstall = routin_ReadRegistry("SOFTWARE\\ESRI\\CoreRuntime");
wndSymbologyControl.LoadStyleFile(sInstall + "\\Styles\\ESRI.ServerStyle");
wndSymbologyControl.StyleClass = styleClass;
m_SymbologyStyleClass = wndSymbologyControl.GetStyleClass(wndSymbologyControl.StyleClass);
m_SymbologyStyleClass.SelectItem(0);
}
方法2:通过IStyleGalleryClass的Preview方法获取符号的预览图
private Image PreViewMarkerSymbol(ISymbol pSymbol, int width, int height)
{
IStyleGalleryClass pStyleGalleryClass = new MarkerSymbolStyleGalleryClass();
Image img = new Bitmap(width, height);
Graphics gc = Graphics.FromImage(img);
IntPtr hdc = gc.GetHdc();
tagRECT rect = new tagRECT();
rect.left = 0;
rect.top = 0;
rect.right = width;
rect.bottom = height;
pStyleGalleryClass.Preview(pSymbol, hdc.ToInt32(), ref rect);
gc.ReleaseHdc(hdc);
gc.Dispose();
return img;
}
private void checkEdit2_CheckedChanged(object sender, EventArgs e)
{
if (m_bLoading) return;
if (mMapGrid != null)
{
if (checkEdit2.Checked)
{
mMapGrid.LineSymbol = null;
ISimpleMarkerSymbol pSimpleMarkerSymbol = new SimpleMarkerSymbol();
pSimpleMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSCross;
IMarkerSymbol pMarkerSymbol = pSimpleMarkerSymbol as IMarkerSymbol;
mMapGrid.TickMarkSymbol = pMarkerSymbol;
mMapGrid.SetLabelVisibility(true, true, true, true);
simpleButton1.Image = PreViewMarkerSymbol(pMarkerSymbol as ISymbol, simpleButton1.Height, simpleButton1.Width);
if (ValueChanged != null) ValueChanged();
}
}
}
使用第二种方法时,要注意ISymbol对象的类型。因为所有符号集类都实现了IStyleGalleryClass接口,如MarkerSymbolStyleGalleryClass、LineSymbolStyleGalleryClass、
ScaleBarStyleGalleryClass等。生成预览图时,各符号的预览图只能由与其对应的StyleGalleryClass来生成,也就是说NorthArrow类型的符号只能用
NorthArrowStyleGalleryClass来预览,而不能用其它类型,像下面这样是会发生异常的:
private void checkEdit3_CheckedChanged(object sender, EventArgs e)
{
if (m_bLoading) return;
if (mMapGrid != null)
{
if (checkEdit3.Checked)
{
ISimpleLineSymbol pSimpleLineSymbol = new SimpleLineSymbol();
pSimpleLineSymbol.Style = esriSimpleLineStyle.esriSLSSolid;
ILineSymbol pLineSymbol = pSimpleLineSymbol as ILineSymbol;
mMapGrid.LineSymbol = pLineSymbol;
mMapGrid.TickMarkSymbol = null;
mMapGrid.SetLabelVisibility(true, true, true, true);
simpleButton1.Image = PreViewMarkerSymbol(pLineSymbol as ISymbol, simpleButton1.Height, simpleButton1.Width);
if (ValueChanged != null) ValueChanged();
}
}
}
这里,传入的是LineSymbol对象,在PreViewMarkerSymbol中,用MarkerSymbolStyleGalleryClass的事例来预览一个LineSymbol,程序在调用Preview时,会直接崩溃,正确的用法是:
private Image PreViewLineSymbol(ISymbol pSymbol, int width, int height)
{
IStyleGalleryClass pStyleGalleryClass = new LineSymbolStyleGalleryClass();
Image img = new Bitmap(width, height);
Graphics gc = Graphics.FromImage(img);
IntPtr hdc = gc.GetHdc();
tagRECT rect = new tagRECT();
rect.left = 0;
rect.top = 0;
rect.right = width;
rect.bottom = height;
pStyleGalleryClass.Preview(pSymbol, hdc.ToInt32(), ref rect);
gc.ReleaseHdc(hdc);
gc.Dispose();
return img;
}
private void checkEdit3_CheckedChanged(object sender, EventArgs e)
{
if (m_bLoading) return;
if (mMapGrid != null)
{
if (checkEdit3.Checked)
{
ISimpleLineSymbol pSimpleLineSymbol = new SimpleLineSymbol();
pSimpleLineSymbol.Style = esriSimpleLineStyle.esriSLSSolid;
ILineSymbol pLineSymbol = pSimpleLineSymbol as ILineSymbol;
mMapGrid.LineSymbol = pLineSymbol;
mMapGrid.TickMarkSymbol = null;
mMapGrid.SetLabelVisibility(true, true, true, true);
simpleButton1.Image = PreViewLineSymbol(pLineSymbol as ISymbol, simpleButton1.Height, simpleButton1.Width);
if (ValueChanged != null) ValueChanged();
}
}
}
实际上IStyleGalleryItem的Item成员,都是ISymbol成员,因此一个ISymbol对象,除了可以直接用IStyleGalleryClass的Previe预览以外,还可以转换成IStyleGalleryItem然后使用ISymbologyStyleClass的Preview方法来预览,比如:
IStyleGalleryItem pStyleGalleryItem = new ServerStyleGalleryItemClass();
IClone pClone = pScaleBar as IClone;
pStyleGalleryItem.Item = pClone.Clone();
之后就可以使用第一种方法来生成预览图了。
下面是自制的符号选择器: