WPF InkCanvas基本操作方法详解
程序员文章站
2023-12-14 10:12:52
wpf的inkcanvas就是一个画板,可以在上面随意涂鸦,每写上一笔,inkcanvas的strokes集合里就新增一个涂鸦对象,下面的代码演示了基本的操作。
效果...
wpf的inkcanvas就是一个画板,可以在上面随意涂鸦,每写上一笔,inkcanvas的strokes集合里就新增一个涂鸦对象,下面的代码演示了基本的操作。
效果图
xaml代码
<window x:class="wpf_inkcanvas.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:wpf_inkcanvas" mc:ignorable="d" title="mainwindow" height="450" width="800"> <grid> <grid.rowdefinitions> <rowdefinition/> <rowdefinition height="auto"/> <rowdefinition height="auto"/> </grid.rowdefinitions> <image name="imgmeasure" horizontalalignment="center" stretch="uniform"/> <inkcanvas name="inkcanvasmeasure" editingmode="none" background="transparent" horizontalalignment="center" width="{binding elementname=imgmeasure, path=actualwidth}" height="{binding elementname=imgmeasure, path=actualheight}" > <!--mousedown="inkcanvasmeasure_mousedown" mousemove="inkcanvasmeasure_mousemove"--> <label content="{binding meainfo}" background="transparent" horizontalalignment="left" verticalalignment="top" margin="10" fontsize="18" foreground="red" ishittestvisible="false"/> </inkcanvas> <grid grid.row="1"> <grid.columndefinitions> <columndefinition/> <columndefinition/> <columndefinition/> <columndefinition/> <columndefinition/> </grid.columndefinitions> <radiobutton grid.column="0" content="绘制墨迹" click="radiobutton_click"/> <radiobutton grid.column="1" content="按点擦除" click="radiobutton_click"/> <radiobutton grid.column="2" content="按线擦除" click="radiobutton_click"/> <radiobutton grid.column="3" content="选中墨迹" click="radiobutton_click"/> <radiobutton grid.column="4" content="停止操作" click="radiobutton_click"/> </grid> <stackpanel grid.row="2" orientation="horizontal"> <button content="openfile" margin="5" horizontalalignment="left" fontsize="20" click="openfile_click"/> <button content="saveinkcanvas" margin="5" horizontalalignment="left" fontsize="20" click="saveinkcanvas_click"/> <button content="loadinkcanvas" margin="5" horizontalalignment="left" fontsize="20" click="loadinkcanvas_click"/> <button content="copyinkcanvas" margin="5" horizontalalignment="left" fontsize="20" click="copyinkcanvas_click"/> <button content="pasteinkcanvas" margin="5" horizontalalignment="left" fontsize="20" click="pasteinkcanvas_click"/> </stackpanel> </grid> </window>
后台代码
using microsoft.win32; using system; using system.collections.generic; using system.io; using system.linq; using system.text; using system.threading.tasks; using system.windows; using system.windows.controls; using system.windows.data; using system.windows.documents; using system.windows.ink; using system.windows.input; using system.windows.media; using system.windows.media.imaging; using system.windows.navigation; using system.windows.shapes; namespace wpf_inkcanvas { /// <summary> /// mainwindow.xaml 的交互逻辑 /// </summary> public partial class mainwindow : window { viewmodel viewmodel; public mainwindow() { initializecomponent(); drawingattributes drawingattributes = new drawingattributes { color = colors.red, width = 2, height = 2, stylustip = stylustip.rectangle, fittocurve = true, ishighlighter = false, ignorepressure = true, }; inkcanvasmeasure.defaultdrawingattributes = drawingattributes; viewmodel = new viewmodel { meainfo = "测试······", }; datacontext = viewmodel; } private void inkcanvasmeasure_mousedown(object sender, mousebuttoneventargs e) { } private void inkcanvasmeasure_mousemove(object sender, mouseeventargs e) { } private void openfile_click(object sender, routedeventargs e) { openfiledialog opendialog = new openfiledialog { filter = "image files (*.jpg)|*.jpg|image files (*.png)|*.png|image files (*.bmp)|*.bmp", title = "open image file" }; if (opendialog.showdialog() == true) { bitmapimage image = new bitmapimage(); image.begininit(); image.urisource = new uri(opendialog.filename, urikind.relativeorabsolute); image.endinit(); imgmeasure.source = image; } } private void radiobutton_click(object sender, routedeventargs e) { if ((sender as radiobutton).content.tostring() == "绘制墨迹") { inkcanvasmeasure.editingmode = inkcanvaseditingmode.ink; } else if ((sender as radiobutton).content.tostring() == "按点擦除") { inkcanvasmeasure.editingmode = inkcanvaseditingmode.erasebypoint; } else if ((sender as radiobutton).content.tostring() == "按线擦除") { inkcanvasmeasure.editingmode = inkcanvaseditingmode.erasebystroke; } else if ((sender as radiobutton).content.tostring() == "选中墨迹") { inkcanvasmeasure.editingmode = inkcanvaseditingmode.select; } else if ((sender as radiobutton).content.tostring() == "停止操作") { inkcanvasmeasure.editingmode = inkcanvaseditingmode.none; } } private void saveinkcanvas_click(object sender, routedeventargs e) { filestream filestream = new filestream("inkcanvas.isf", filemode.create, fileaccess.readwrite); inkcanvasmeasure.strokes.save(filestream); filestream.close(); } private void loadinkcanvas_click(object sender, routedeventargs e) { filestream filestream = new filestream("inkcanvas.isf", filemode.open, fileaccess.read); inkcanvasmeasure.strokes = new strokecollection(filestream); filestream.close(); } private void copyinkcanvas_click(object sender, routedeventargs e) { inkcanvasmeasure.copyselection(); } private void pasteinkcanvas_click(object sender, routedeventargs e) { inkcanvasmeasure.paste(); } } }
viewmodel.cs代码
using system; using system.collections.generic; using system.componentmodel; using system.linq; using system.text; using system.threading.tasks; namespace wpf_inkcanvas { class viewmodel : inotifypropertychanged { public event propertychangedeventhandler propertychanged; protected virtual void onpropertychanged(string propertyname = null) { if (propertychanged != null) propertychanged.invoke(this, new propertychangedeventargs(propertyname)); } private string meainfo; public string meainfo { get => meainfo; set { meainfo = value; onpropertychanged("meainfo"); } } } }
补充说明:将image和inkcanvas放到一个grid里,并且将inkcanvas的长宽绑定到image,这样image和inkcanvas的位置就是对应的,方便我后续在inkcanvas上提取image的感兴趣区域;inkcanvas里加了一个label可以实现类似图片上添加文字说明的功能,要设置label的ishittestvisible="false",不然点击事件就没办法触发了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。