using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; using POSV.MessageEvent; using POSV.Utils; using POSV.Bean; using POSV.Entity; using DevComponents.DotNetBar.Metro; using DevComponents.DotNetBar; using System.Runtime.InteropServices; using System.Threading; using POSV.ShoppingCart; namespace POSV.Component { [ToolboxItem(true)] public partial class ProductControl : BaseUserControl { /// /// 数据源 /// private List _dataSource = null; /// /// 键盘、方向键、搜索操作标识 /// private KeyboardAction _action = KeyboardAction.None; /// /// 当前焦点索引 /// private int _index = 0; /// /// 当前焦点单品 /// private MetroTileItem _curr = null; public ProductControl() { InitializeComponent(); this.BackColor = Color.Transparent; //订购界面变更通知事件 MsgEvent.Receive(Constant.PRODUCT_CHANGED_NOTIFY , this.ProductChangedEventNotify); //订购沽清通知事件 MsgEvent.Receive(Constant.SALE_CLEAR_CHANGED_NOTIFY , this.SaleClearChangedEventNotify); //单品键盘通知事件 MsgEvent.Receive(Constant.PRODUCT_KEYBOARD_NOTIFY , this.ProductKeyboardEventNotify); } protected void ProductKeyboardEventNotify(object sender , MsgEventArgs args) { if (args != null && args.Data != null) { Enum.TryParse(args.Data.ToString() , out this._action); switch (this._action) { case KeyboardAction.Left: { if (this.itemPanel.Items.Count > 0) { var container = this.itemPanel.Items[0] as ItemContainer; int subItems = container.SubItems.Count; //只有一个单品 if(subItems == 1) { //当前操作的 this._index = 0; this._curr = container.SubItems[this._index] as MetroTileItem; this.UpdateSelectedStyle(this._curr); } if (this._index - 1 >= 0) { //当前操作的,重置样式 var focus = container.SubItems[this._index] as MetroTileItem; this.ResetMetroTileItemStyle(focus); //当前操作的 this._index = this._index - 1; this._curr = container.SubItems[this._index] as MetroTileItem; this.UpdateSelectedStyle(this._curr); } } } break; case KeyboardAction.Right: { if (this.itemPanel.Items.Count > 0) { var container = this.itemPanel.Items[0] as ItemContainer; int subItems = container.SubItems.Count; //只有一个单品 if (subItems == 1) { //当前操作的 this._index = 0; this._curr = container.SubItems[this._index] as MetroTileItem; this.UpdateSelectedStyle(this._curr); } if (this._index + 1 < subItems) { //重置当前样式 var focus = container.SubItems[this._index] as MetroTileItem; this.ResetMetroTileItemStyle(focus); //当前操作的 this._index = this._index + 1; this._curr = container.SubItems[this._index] as MetroTileItem; this.UpdateSelectedStyle(this._curr); } } } break; case KeyboardAction.Up: { if (this.itemPanel.Items.Count > 0) { var container = this.itemPanel.Items[0] as ItemContainer; int subItems = container.SubItems.Count; //只有一个单品 if (subItems == 1) { //当前操作的 this._index = 0; this._curr = container.SubItems[this._index] as MetroTileItem; this.UpdateSelectedStyle(this._curr); } if (this._index - this.Columns >= 0) { //重置当前样式 var focus = container.SubItems[this._index] as MetroTileItem; this.ResetMetroTileItemStyle(focus); //当前操作的 this._index = this._index - this.Columns; this._curr = container.SubItems[this._index] as MetroTileItem; this.UpdateSelectedStyle(this._curr); } } } break; case KeyboardAction.Down: { if (this.itemPanel.Items.Count > 0) { var container = this.itemPanel.Items[0] as ItemContainer; int subItems = container.SubItems.Count; //只有一个单品 if (subItems == 1) { //当前操作的 this._index = 0; this._curr = container.SubItems[this._index] as MetroTileItem; this.UpdateSelectedStyle(this._curr); } if (this._index + this.Columns < subItems) { //重置当前样式 var focus = container.SubItems[this._index] as MetroTileItem; this.ResetMetroTileItemStyle(focus); //当前操作的 this._index = this._index + Columns; this._curr = container.SubItems[this._index] as MetroTileItem; this.UpdateSelectedStyle(this._curr); } } } break; case KeyboardAction.Search: { if (this.itemPanel.Items.Count > 0) { var container = this.itemPanel.Items[0] as ItemContainer; if(container.SubItems.Count > 0) { this._index = 0; this._curr = container.SubItems[this._index] as MetroTileItem; this.UpdateSelectedStyle(this._curr); } LOGGER.Info(">>>>>*****>>>>>{0}" , this._curr != null ? this._curr.Text : "&&&&&"); } } break; case KeyboardAction.Enter: { LOGGER.Info(">>>>>*****>>>>>Enter>>>>{0}" , this._curr == null ? "" : this._curr.Name); if (this._curr != null) { var r = this.RectangleToScreen(this._curr.DisplayRectangle); int dx = (r.Left + this._curr.TileSize.Width / 2); int dy = (r.Top + this._curr.TileSize.Height / 2); var e = new MouseEventArgs(MouseButtons.Left , 1 , dx , dy , 0); SetCursorPos(dx, dy); LOGGER.Info(">>>>>*****>>>>>{0},{1}" , dx,dy); this.OnItemMouseDown(this._curr , e); } } break; } } } [DllImport("User32.dll")] private static extern bool SetCursorPos(int x , int y); public void UpdateSelectedStyle(MetroTileItem item) { item.TileStyle.Font = this.GetSystemFont(this.SelProductFont); item.TileStyle.TextColor = ColorTranslator.FromHtml(this.SelTextColor); item.TitleTextColor = ColorTranslator.FromHtml(this.SelTextColor); item.TileStyle.BackColor = ColorTranslator.FromHtml(this.SelBackColor); item.TileStyle.BackColor2 = ColorTranslator.FromHtml(this.SelBackColor); item.TileStyle.BorderColor = ColorTranslator.FromHtml(this.SelBackColor); item.TileStyle.BorderColor2 = ColorTranslator.FromHtml(this.SelBackColor); } protected void SaleClearChangedEventNotify(object sender , MsgEventArgs args) { if(this.itemPanel.Items.Count > 0) { var saleClear = args.Data as SaleClear; var container = this.itemPanel.Items[0] as ItemContainer; LOGGER.Info("当前沽清记录数量:{0}" , SaleClearUtils.Instance.Maps.Count); if (container.SubItems.Contains(saleClear.ProductId)) { var item = container.SubItems[saleClear.ProductId]; var metro = item as MetroTileItem; var entity = metro.Tag as ProductExt; entity.SaleClear = this.getSaleClear(entity.Id); this.UpdateSaleClear(metro , entity); } } } public void ResetMetroTileItemStyle(MetroTileItem item) { var entity = item.Tag as ProductExt; switch (entity.Name) { case Constant.PREV_PAGER: { item.TileStyle.BackColor = ColorTranslator.FromHtml(this.PagerColor1); item.TileStyle.BackColor2 = ColorTranslator.FromHtml(this.PagerColor2); //item.TileStyle.BorderColor = ColorTranslator.FromHtml(this.PagerColor1); //item.TileStyle.BorderColor2 = ColorTranslator.FromHtml(this.PagerColor2); } break; case Constant.NEXT_PAGER: { item.TileStyle.BackColor = ColorTranslator.FromHtml(this.PagerColor1); item.TileStyle.BackColor2 = ColorTranslator.FromHtml(this.PagerColor2); //item.TileStyle.BorderColor = ColorTranslator.FromHtml(this.PagerColor1); //item.TileStyle.BorderColor2 = ColorTranslator.FromHtml(this.PagerColor2); } break; default: { item.TileStyle.Font = this.GetSystemFont(this.FontSize); item.TileStyle.TextColor = ColorTranslator.FromHtml(this.TextColor); item.TitleTextColor = ColorTranslator.FromHtml(this.TextColor); item.TileStyle.BackColor = ColorTranslator.FromHtml(this.BackColor1); item.TileStyle.BackColor2 = ColorTranslator.FromHtml(this.BackColor2); //item.TileStyle.BorderColor = ColorTranslator.FromHtml(this.BackColor1); //item.TileStyle.BorderColor2 = ColorTranslator.FromHtml(this.BackColor2); this.UpdateSaleClear(item , entity); } break; } } protected void ProductChangedEventNotify(object sender , MsgEventArgs args) { if (args.Data is ProductItem) { var data = args.Data as ProductItem; Global.Instance.ReloadConfig(ConfigConstant.PRODUCT_GROUP); this.RefreshUi(data); this.BindDataSource(this._dataSource); } } protected override void OnPaint(PaintEventArgs e) { //base.OnPaint(e); Rectangle rect = new Rectangle(0 , 0 , this.Width , this.Height); ControlPaint.DrawBorder(e.Graphics , rect , Color.Transparent , ButtonBorderStyle.Solid);//画个边框 //ControlPaint.DrawBorder(e.Graphics , rect , // Color.Transparent , 1 , ButtonBorderStyle.Solid , // Color.Transparent , 1 , ButtonBorderStyle.Solid , // Color.Transparent , 1 , ButtonBorderStyle.Solid , // Color.Transparent , 1 , ButtonBorderStyle.Solid //); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); if (this.DesignMode) return; var productJsonTemplate = Global.Instance.GlobalConfigStringValue(ConfigConstant.PRODUCT_JSON_TEMPLATE); if (string.IsNullOrEmpty(productJsonTemplate)) { productJsonTemplate = JsonUtils.Serialize(new ProductItem()); } this.RefreshUi(JsonUtils.Deserialize(productJsonTemplate)); //当前页码 this.PageNumber = 1; } public void RefreshUi(ProductItem item) { this.FontSize = item.ProductFont; this.Columns = item.Columns; this.ItemWidth = item.ItemWidth; this.ItemHeight = item.ItemHeight; this.BackColor1 = item.BackColor1; this.BackColor2 = item.BackColor2; this.TextColor = item.TextColor; this.PagerColor1 = item.PagerColor1; this.PagerColor2 = item.PagerColor2; this.ShowType = item.ShowType; this.SaleClearColor = item.SaleClearColor; this.SaleClearFont = item.SaleClearFont; this.SaleClearTextColor = item.SaleClearTextColor; this.SaleStopColor = item.SaleStopColor; this.SaleClearNotifyColor = item.SaleClearNotifyColor; this.SelBackColor = item.SelBackColor; this.SelTextColor = item.SelTextColor; this.SelProductFont = item.SelProductFont; this.ProductCornerType = item.ProductCornerType; UpdateTemplate(); } private void UpdateTemplate() { } private MetroTileItem GetItemTemplate() { MetroTileItem template = new MetroTileItem(); template.TileStyle.PaddingLeft = template.TileStyle.PaddingRight = -2; template.EnableMarkup = true; template.OptionGroup = "Dish"; template.TileStyle.Font = this.itemPanel.Font; switch (this.ShowType) { case ProductShowType.全称和零售价: case ProductShowType.简称和零售价: { template.TileStyle.TextAlignment = DevComponents.DotNetBar.eStyleTextAlignment.Center; template.TileStyle.TextLineAlignment = DevComponents.DotNetBar.eStyleTextAlignment.Near; template.TitleTextAlignment = System.Drawing.ContentAlignment.BottomCenter; } break; case ProductShowType.品项全称: case ProductShowType.品项简称: { template.TileStyle.TextAlignment = DevComponents.DotNetBar.eStyleTextAlignment.Center; template.TileStyle.TextLineAlignment = DevComponents.DotNetBar.eStyleTextAlignment.Center; } break; } template.TileStyle.TextColor = ColorTranslator.FromHtml(this.TextColor); template.TitleTextColor = ColorTranslator.FromHtml(this.TextColor); template.TileStyle.BackColor = ColorTranslator.FromHtml(this.BackColor1); template.TileStyle.BackColor2 = ColorTranslator.FromHtml(this.BackColor1); template.TileStyle.BorderColor = Color.Transparent; //ColorTranslator.FromHtml(this.BackColor1); template.TileStyle.BorderColor2 = Color.Transparent;// ColorTranslator.FromHtml(this.BackColor1); template.TileStyle.BorderWidth = 1; template.TileStyle.CornerDiameter = 4; switch (this.ProductCornerType) { case CornerType.默认: { template.TileStyle.CornerType = eCornerType.Square; } break; case CornerType.圆角: { template.TileStyle.CornerType = eCornerType.Rounded; template.TileStyle.BorderColor = ColorTranslator.FromHtml(this.BackColor1); template.TileStyle.BorderColor2 = ColorTranslator.FromHtml(this.BackColor1); } break; case CornerType.棱角: { template.TileStyle.CornerType = eCornerType.Diagonal; } break; } //显示大小 template.TileSize = new Size(this.ItemWidth , this.ItemHeight); template.MouseDown += OnItemMouseDown; return template; } private void OnItemMouseDown(object sender , MouseEventArgs e) { if(e.Button == MouseButtons.Left) { MetroTileItem item = (MetroTileItem)sender; var product = item.Tag as ProductExt; switch (product.Name) { case Constant.PREV_PAGER: { int pageNumber = 1; int.TryParse(product.Memo,out pageNumber); this.PageNumber = pageNumber; this.BindDataSource(this._dataSource); } break; case Constant.NEXT_PAGER: { int pageNumber = 1; int.TryParse(product.Memo , out pageNumber); this.PageNumber = pageNumber; this.BindDataSource(this._dataSource); } break; default: { this.OnProductCheckedChanged(new ProductEventArgs(product)); } break; } } } public event ProductEventHandler ProductCheckedChanged; protected virtual void OnProductCheckedChanged(ProductEventArgs e) { ProductCheckedChanged?.Invoke(this , e); } private SaleClear getSaleClear(string productId) { //判断是否存在沽清 SaleClear saleClear = null; if (SaleClearUtils.Instance.Maps.ContainsKey(productId)) { saleClear = SaleClearUtils.Instance.Maps[productId]; } return saleClear; } public void BindDataSource(List dataSource, KeyboardAction action = KeyboardAction.None) { this._dataSource = dataSource; this._action = action; this._index = 0; this._curr = null; LOGGER.Trace("单品绑定操作<{0},{1}>" , this._action.ToString() , this._dataSource.Count); if (this._dataSource == null) { this._dataSource = new List(); } //总数量 this.TotalCount = dataSource.Count; //每页的显示数量 this.PageSize = this.Rows * this.Columns; //清空历史数据 this.itemPanel.Items.Clear(); this.itemPanel.Font = this.GetSystemFont(this._fontSize); //复制新的数据源,进行分页运算 var merge = ProductMerge.Merge(this.Rows , this.Columns , dataSource , false); var pager = ListPager(merge); ItemContainer ic = new ItemContainer(); ic.MultiLine = true; ic.ItemSpacing = 0; ic.LayoutOrientation = eOrientation.Horizontal; foreach (ProductExt entity in pager) { //否存在沽清 entity.SaleClear = getSaleClear(entity.Id); MetroTileItem item = this.GetItemTemplate(); item.Name = entity.Id; item.Checked = false; //绑定品类ID到Tag属性 item.Tag = entity; switch (entity.Name) { case Constant.PREV_PAGER: { item.Image = POSV.Properties.Resources.left; item.ImageTextAlignment = System.Drawing.ContentAlignment.MiddleCenter; item.TileStyle.BackColor = ColorTranslator.FromHtml(this.PagerColor1); item.TileStyle.BackColor2 = ColorTranslator.FromHtml(this.PagerColor2); //item.TileStyle.BorderColor = Color.Transparent; //item.TileStyle.BorderColor2 = Color.Transparent; } break; case Constant.NEXT_PAGER: { item.Image = POSV.Properties.Resources.right; item.ImageTextAlignment = System.Drawing.ContentAlignment.MiddleCenter; item.TileStyle.BackColor = ColorTranslator.FromHtml(this.PagerColor1); item.TileStyle.BackColor2 = ColorTranslator.FromHtml(this.PagerColor2); //item.TileStyle.BorderColor = Color.Transparent; //item.TileStyle.BorderColor2 = Color.Transparent; } break; default: { switch (this.ShowType) { case ProductShowType.全称和零售价: case ProductShowType.简称和零售价: { //绑定品类售价 item.TitleText = entity.Price + ""; //绑定品类名称 item.Text = entity.Name; } break; case ProductShowType.品项全称: case ProductShowType.品项简称: { //绑定品类名称到Text属性 item.Text = entity.Name; } break; } //促销 UpdatePromotion(item, entity); //沽清 UpdateSaleClear(item , entity); } break; } ic.SubItems.Add(item); } this.itemPanel.Items.Add(ic); this.itemPanel.Invalidate(); } public void UpdatePromotion(MetroTileItem item, ProductExt entity) { try { var res = PromotionEngine.Instance.GetSpecPromotionPrice(entity); if (res.Item1) { if (!string.IsNullOrEmpty(item.TitleText)) { item.TitleText = StringUtils.FormatDataNoDigit(res.Item2); } item.NotificationMarkColor = Color.DarkRed; item.NotificationMarkText = "促"; item.NotificationMarkSize = 20; item.NotificationMarkPosition = eNotificationMarkPosition.BottomRight; } else { item.TitleTextColor = ColorTranslator.FromHtml(this.TextColor); item.NotificationMarkText = string.Empty; item.NotificationMarkSize = 0; item.NotificationMarkPosition = eNotificationMarkPosition.BottomRight; } } catch(Exception ex) { LOGGER.Error(ex, "加载商品块:获取商品促销信息异常!"); } } public void UpdateSaleClear(MetroTileItem item,ProductExt entity) { if (entity.SaleClear != null) { if (entity.SaleClear.StopFlag == 0 && !entity.SaleClear.Frozen) { item.TileStyle.Font = this.GetSystemFont(this.SaleClearFont); if (entity.SaleClear.Quantity > 0) { item.TileStyle.TextColor = ColorTranslator.FromHtml(this.SaleClearTextColor); item.TitleTextColor = ColorTranslator.FromHtml(this.SaleClearTextColor); item.TileStyle.BackColor = ColorTranslator.FromHtml(this.SaleClearColor); item.TileStyle.BackColor2 = ColorTranslator.FromHtml(this.SaleClearColor); item.TileStyle.BorderColor = Color.Transparent; item.TileStyle.BorderColor2 = Color.Transparent; item.NotificationMarkColor = ColorTranslator.FromHtml(this.SaleClearNotifyColor); item.NotificationMarkText = entity.SaleClear.Quantity.ToString(); item.NotificationMarkSize = 20; } else { item.TileStyle.TextColor = ColorTranslator.FromHtml(this.SaleClearTextColor); item.TitleTextColor = ColorTranslator.FromHtml(this.SaleClearTextColor); item.TileStyle.BackColor = ColorTranslator.FromHtml(this.SaleStopColor); item.TileStyle.BackColor2 = ColorTranslator.FromHtml(this.SaleStopColor); item.TileStyle.BorderColor = Color.Transparent; item.TileStyle.BorderColor2 = Color.Transparent; item.NotificationMarkColor = ColorTranslator.FromHtml(this.SaleClearNotifyColor); item.NotificationMarkText = "停"; item.NotificationMarkSize = 20; } } else { item.TileStyle.TextColor = ColorTranslator.FromHtml(this.TextColor); item.TitleTextColor = ColorTranslator.FromHtml(this.TextColor); item.TileStyle.BackColor = ColorTranslator.FromHtml(this.BackColor1); item.TileStyle.BackColor2 = ColorTranslator.FromHtml(this.BackColor2); item.TileStyle.BorderColor = Color.Transparent; item.TileStyle.BorderColor2 = Color.Transparent; item.NotificationMarkText = string.Empty; item.NotificationMarkSize = 0; } item.Refresh(); } } /// /// 分页List数据 /// /// /// public List ListPager(List data) { var result = new List(); result.AddRange(data.Skip((this.PageNumber - 1) * this.PageSize).Take(this.PageSize)); return result; } private ProductShowType _showType = ProductShowType.全称和零售价; public ProductShowType ShowType { get { return this._showType; } set { this._showType = value; } } private int _itemHeight = 70; /// ///品类显示的高度 /// public int ItemHeight { get { return _itemHeight; } set { _itemHeight = (value <= 0 ? 70 : value); } } private int _itemWidth = 90; /// /// 品类的宽度 /// public int ItemWidth { get { return this._itemWidth; } set { if (value <= 0 || ((value * this._columns) > this.ContentWidth)) { this._itemWidth = this.ContentWidth / this._columns; } else { this._itemWidth = value; this._columns = this.ContentWidth / this._itemWidth; } } } private SystemFont _fontSize = SystemFont.默认; /// /// 字体大小 /// public SystemFont FontSize { get { return this._fontSize; } set { this._fontSize = value; } } private string _backColor1 = ColorTranslator.ToHtml(Color.DimGray); /// /// 品类显示颜色 /// public string BackColor1 { get { return this._backColor1; } set { this._backColor1 = value; } } private string _backColor2 = ColorTranslator.ToHtml(Color.DimGray); /// /// 品类显示颜色 /// public string BackColor2 { get { return this._backColor2; } set { this._backColor2 = value; } } private string _textColor = ColorTranslator.ToHtml(Color.White); /// /// 品类显示颜色 /// public string TextColor { get { return this._textColor; } set { this._textColor = value; } } /// /// 有效区域的宽度,不包含左右分页宽度 /// public int ContentWidth => this.Width /*- this.PagerWidth - (this.Columns + 1)*/; public int ContentHeight => this.Height; private string _pagerColor1 = ColorTranslator.ToHtml(Color.DimGray); /// /// 分页按钮的颜色 /// public string PagerColor1 { get { return this._pagerColor1; } set { this._pagerColor1 = value; } } private string _pagerColor2 = ColorTranslator.ToHtml(Color.DimGray); /// /// 分页按钮的颜色 /// public string PagerColor2 { get { return this._pagerColor2; } set { this._pagerColor2 = value; } } private bool _autoPager = true; /// /// 是否自动隐藏分页 /// public bool AutoPager { get { return this._autoPager; } set { this._autoPager = value; } } /// /// 每页的大小 /// public int PageSize { get; private set; } /// /// 总页数 /// public int PageCount => this.PageSize <= 0 ? 0 : ((this.TotalCount + this.PageSize - 1) / this.PageSize); /// /// 当前页码 /// public int PageNumber { get; set; } /// /// 总数量 /// public int TotalCount { get; private set; } private int _columns = 1; /// /// 每一行显示的数量 /// public int Columns { get { return _columns; } set { _columns = (value <= 0 ? 1 : value); } } /// ///品类默认行数 /// public int Rows => this.Height / this.ItemHeight; //是否有上一页 public bool HasPreviousPage { get { return PageNumber > 1; } } //是否有下一页 public bool HasNextPage { get { return PageNumber < this.PageCount; } } /// /// 沽清品类显示颜色 /// public string SaleClearColor { get; set; } /// /// 沽清品类提醒颜色 /// public string SaleClearNotifyColor { get; set; } /// /// 沽清字体显示颜色 /// public string SaleClearTextColor { get; set; } /// /// 沽清的字体大小 /// public SystemFont SaleClearFont { get; set; } /// /// 沽清停售显示颜色 /// public string SaleStopColor { get; set; } /// /// 选中品项显示颜色 /// public string SelBackColor { get; set; } /// /// 选中字体显示颜色 /// public string SelTextColor { get; set; } /// /// 选中品项的字体 /// public SystemFont SelProductFont { get; set; } /// /// 品项的显示样式 /// public CornerType ProductCornerType { get; set; } = CornerType.圆角; } public delegate void ProductEventHandler(object sender , ProductEventArgs e); public class ProductEventArgs : EventArgs { public ProductExt Product; public ProductEventArgs(ProductExt data) { this.Product = data; } } }