问题描述:后端功能函数返回的结果是List。展示图片的方式是:遍历所有后端返回的表情对象,按路径将表情存入imageList组件,再将imageList中的图片展示到DataGridView的单元格中。这样在选中单元格时,选中的不是Emoji对象,而是图片本身。
解决方案:设置一个静态变量public static List emojiList = new List();用来保存当前界面中显示的图片对应的对象。界面在初始化时规定好了一共展示多少行row多少列col,当前行r、列c索引和emojiList下标的对应关系为:
location = r * col + c;
展示图片的函数:
public void ShowEmojis(List<Emoji> emojis)
{
//清空图片数据
imageList.Images.Clear();
for (int r = 0; r < row; r++)
{
for (int c = 0; c < col; c++)
{
this.dataGridViewImage[c, r].Value = null;
}
}
//防止图片失真
this.imageList.ColorDepth = ColorDepth.Depth32Bit;
//当数据库图片不为空时,将图片加入imageList
if (emojis.Count != 0)
{
foreach (Emoji e in emojis)
{
if (e.Path != "")
{
try
{
this.imageList.Images.Add(System.Drawing.Image.FromFile(e.Path));
}
catch (System.IO.FileNotFoundException) { }
}
}
//Console.WriteLine("real:" + realcount+"emojicount:"+emojis.Count);
//展示图片
int count = 0;
for (int r = 0; r < row; r++)
{
for (int c = 0; c < col; c++)
{
if (count < imageList.Images.Count)
{
this.dataGridViewImage[c, r].Value = imageList.Images[count++];
}
else return;
}
}
}
this.Refresh();
}
解决方案:当前窗口的DragDrop和DragEnter委托分别订阅两个自定义函数:
DragDrop += AddForm_DragDrop;
DragEnter += AddForm_DragEnter;
自定义函数如下:
private void AddForm_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Link;
else e.Effect = DragDropEffects.None;
}
private void AddForm_DragDrop(object sender, DragEventArgs e)
{
//得到路径
string path = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
//显示图片
this.pictureBox1.Image=Image.FromFile(path);
//接着这里调用OCR
… …
//将信息填充进文本框
… …
}
解决方案:难点在于:鼠标所在位置到DataGridView中单元格行列的映射。无法鼠标悬停时选中Emoji对象,因此无法展示图片数据。似乎没有好的解决方案。所以最后放弃了鼠标悬停显示图片信息,转而在鼠标左键点击图片选中图片对象时在当前鼠标所在位置显示ToolTip组件,展示图片信息。(ToolTip展示方式为:1.绑定到组件 2.绑定到当前位置。单元格不是组件,因此在鼠标所在位置显示ToolTip)
解决方案:使用ContextMenuStrip控件,右键选中的条件为:
e.Button == MouseButtons.Right
然后再鼠标当前位置显示ContextMenuStrip控件。
//鼠标右键显示菜单
if (e.Button == MouseButtons.Right)
{
int r = dataGridViewImage.CurrentCell.RowIndex;
int c = dataGridViewImage.CurrentCell.ColumnIndex;
int location = r * col + c;
if (location < emojiList.Count)
{
emojiSelected = emojiList[location];
cmsRightClick.Show(MousePosition);
}
}
知乎api
URL参数:
文件名部分:从域名后的最后一个“/”开始到“?”为止,是文件名部分,如果没有“?”,则是从域名后的最后一个“/”开始到“#”为止,是文件部分,如果没有“?”和“#”,那么从域名后的最后一个“/”开始到结束,都是文件名部分。
参数部分:从“?”开始到“#”为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为“boardID=5&ID=24618&page=1”。参数可以允许有多个参数,参数与参数之间用“&”作为分隔符。
锚部分:从“#”开始到最后,都是锚部分。本例中的锚部分是“name”。锚部分也不是一个URL必须的部分
解决方案:图片需要经过base64和Url编码,并转换成字节流发送至服务器。主要代码如下:
public static String getOcrResult(string path)
{
//access_token要定期换
string url = "https://aip.baidubce.com/rest/2.0/ocr/v1/general?access_token="+ getAccessToken();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "post";
request.KeepAlive = true;
string base64 = getFileBase64(path);
String str = "image=" + HttpUtility.UrlEncode(base64);
Encoding encoding = Encoding.UTF8;
byte[] buffer = encoding.GetBytes(str);
request.ContentLength = buffer.Length;
request.GetRequestStream().Write(buffer, 0, buffer.Length);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string result = reader.ReadToEnd();
//处理服务器返回结果得到最后的文字识别结果
… …
}
private static string getFileBase64(string path)
{
FileStream filestream = new FileStream(path, FileMode.Open);
byte[] arr = new byte[filestream.Length];
filestream.Read(arr, 0, (int)filestream.Length);
string base64 = Convert.ToBase64String(arr);
filestream.Close();
return base64;
}