本篇文章将介绍开发医学影像胶片打印系统(printscu模式)遇到不规则排版时的一种思路,

一般来讲,医院打印胶片时都是整张胶片打印,但有时需要将多个病人或一个病人的多个检查打印在同一张胶片上,

这时候就需要不规则排版来满足打印需求,使胶片利用率最大化。

国际惯例,先看效果:

常规打印业务流程:

1、编辑布局模板

2、载入布局模板

3、选择标记模板

4、下载与选择影像

5、微调影像

6、超清预览、发送打印

编辑布局模板:

我们在一个Grid中,通过行数和列数循环创建带边框的Border来显示表格,并添加鼠标事件:

                for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
Border border = new Border
{
Width = w,
Height = h,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top,
Margin = new Thickness(j * w, i * h, 0, 0),
BorderThickness = new Thickness(1),
BorderBrush = ColorHandler.GetColorBrush("#CCCCCC"),
Background = ColorHandler.GetColorBrush("#000000"), };
border.MouseEnter += Border_MouseEnter;
border.MouseLeftButtonDown += Border_MouseLeftButtonDown;
GridTempl.Children.Add(border);
}
}

点击单元格时将改变背景颜色,在鼠标按下时并移动鼠标,触发MouseEnter,选择多个单元格:

因为合并单元格是不能为不规则形状,所以多选的单元格整体必须为一个矩形,

因此多选时首先记录所有选中的单元格,然后通过坐标判断左上角和右下角的单元格位置,这样整体矩形的宽和高的范围就确定了,

在此矩形范围内的单元格将自动全部选中:

但也有特殊情况:如果矩形范围包含大小不一的单元格 这时候计算范围就会不准确:

通过以下几种情况来判断大单元格与小单元格的包含关系:

        /// <summary>
/// 筛选出已经合并的cell并计算最大选中范围
/// </summary>
private void CheckCell()
{
List<Border> bors = new List<Border>();
for (int i = 0; i < GridTempl.Children.Count; i++)
{
Border border = (GridTempl.Children[i] as Border);
if (((SolidColorBrush)border.Background).Color == Color.FromRgb(68, 68, 68))
{
bors.Add(border);
}
} double cellMinLeft = bors[0].Margin.Left;
double cellMaxLeft = 0;
double cellMinTop = bors[0].Margin.Top;
double cellMaxTop = 0;
for (int i = 0; i < bors.Count; i++)
{
if (bors[i].Margin.Left < cellMinLeft)
{
cellMinLeft = bors[i].Margin.Left;
}
if (bors[i].Margin.Top < cellMinTop)
{
cellMinTop = bors[i].Margin.Top;
}
if (bors[i].Margin.Top + bors[i].Height > cellMaxTop)
{
cellMaxTop = bors[i].Margin.Top + bors[i].Height;
}
if (bors[i].Margin.Left + bors[i].Width > cellMaxLeft)
{
cellMaxLeft = bors[i].Margin.Left + bors[i].Width;
}
} for (int i = 0; i < GridTempl.Children.Count; i++)
{
Border otherBor = GridTempl.Children[i] as Border;
if (bors.Contains(otherBor))
{
continue;
} //包含左上角
if (otherBor.Margin.Left > cellMinLeft
&& (otherBor.Margin.Left) < cellMaxLeft
&& otherBor.Margin.Top > cellMinTop
&& (otherBor.Margin.Top) < cellMaxTop)
{
otherBor.Background = ColorHandler.GetColorBrush("#444444");
CheckCell();
return;
} //包含右上角
if (otherBor.Margin.Left + otherBor.Width > cellMinLeft
&& (otherBor.Margin.Left + otherBor.Width) < cellMaxLeft
&& otherBor.Margin.Top > cellMinTop
&& (otherBor.Margin.Top) < cellMaxTop)
{
otherBor.Background = ColorHandler.GetColorBrush("#444444");
CheckCell();
return;
} //包含右下角
if (otherBor.Margin.Left + otherBor.Width > cellMinLeft
&& (otherBor.Margin.Left + otherBor.Width) < cellMaxLeft
&& (otherBor.Margin.Top + otherBor.Height) > cellMinTop
&& (otherBor.Margin.Top + otherBor.Height) < cellMaxTop)
{
otherBor.Background = ColorHandler.GetColorBrush("#444444");
CheckCell();
return;
} //包含左下角
if (otherBor.Margin.Left > cellMinLeft
&& (otherBor.Margin.Left) < cellMaxLeft
&& (otherBor.Margin.Top + otherBor.Height) > cellMinTop
&& (otherBor.Margin.Top + otherBor.Height) < cellMaxTop)
{
otherBor.Background = ColorHandler.GetColorBrush("#444444");
CheckCell();
return;
} //水平分割
if (otherBor.Margin.Left > cellMinLeft
&& (otherBor.Margin.Left) < cellMaxLeft
&& (otherBor.Margin.Top) <= cellMinTop
&& (otherBor.Margin.Top + otherBor.Height) >= cellMaxTop)
{
otherBor.Background = ColorHandler.GetColorBrush("#444444");
CheckCell();
return;
} //垂直分割
if (otherBor.Margin.Left <= cellMinLeft
&& (otherBor.Margin.Left + otherBor.Width) >= cellMaxLeft
&& (otherBor.Margin.Top) > cellMinTop
&& (otherBor.Margin.Top + otherBor.Height) < cellMaxTop)
{
otherBor.Background = ColorHandler.GetColorBrush("#444444");
CheckCell();
return;
}
}
}

通过递归填充单元格达到矩形范围的同行同列自动选择,接下来就可以合并所选择的单元格:

计算最大宽度和最大高度,并且使左上角的单元格等于最大宽高,以实现合并效果:

            //计算最大宽度
double w = borderFirst.Width;
for (int i = 0; i < bors.Count; i++)
{
if (bors[i] != borderFirst && borderFirst.Margin.Top == bors[i].Margin.Top)
{
w += bors[i].Width;
}
} //计算最大高度
double h = borderFirst.Height;
for (int i = 0; i < bors.Count; i++)
{
if (bors[i] != borderFirst && borderFirst.Margin.Left == bors[i].Margin.Left)
{
h += bors[i].Height;
}
} borderFirst.Tag = Math.Round(h / borderFirst.Height) + "#" + Math.Round(w / borderFirst.Width);
borderFirst.Width = w;
borderFirst.Height = h;

看效果:

将布局通过自定义格式保存到本地文件,就可以在排版界面载入布局模板。

编辑标记模板:

选择常用Tag添加到胶片的四个角,以便在后面载入影像的时候读取标记信息:

读取检查列表和下载影像:

可以参考本系列教程文章:

C#开发PACS医学影像处理系统(五):查询病人信息列表

载入影像并微调(平移,缩放,自由旋转等二维操作):

使用1:1像素超清预览查看打印细节:

下载一个打印服务端模拟接受打印:

我这里使用的是模拟激光相机5.0版本,下载地址:https://www.fxxz.com/soft/47115.html

设置好端口并发送,查看握手状态和通讯包:

查看打印结果:

C#开发医学影像胶片打印系统(一):万能花式布局的实现思路的更多相关文章

  1. C#开发PACS医学影像处理系统(二):界面布局之菜单栏

    在菜单栏布局上,为了使用自定义窗体样式和按钮,我们需要先将窗体设置为无边框,然后添加一个Grid作为菜单栏并置顶,VerticalAlignment="Top" logo图片和标题 ...

  2. C#开发PACS医学影像处理系统(三):界面布局之工具栏

    工具栏布局采用WPF中Grid作为容器,按钮采用自定义样式和图标,并采用Separator分割线: XAML设计器代码: 其中  Style="{StaticResource ButtonS ...

  3. 医学影像工作站程序ProDicom的说明

    转载 http://blog.csdn.net/prodicom/article/details/4015064 注意:以下内容为转载,但保留了第一人称,请注意,以免造成不必要的麻烦. 医网联影像工作 ...

  4. SNF快速开发平台MVC-Grid++集成打印

    一.显示效果: 二.程序实现: 1.先要在 打印模版程序 给指定页面进行在线设计打印模版 2.在使用的程序当中,增加如下代码即可.程序上是可以挂多个打印模版的,程序页面的代码不用动直接可以读取到打印模 ...

  5. SNF快速开发平台3.0之--系统里广播的作用--迅速及时、简明扼要的把信息发送给接收者

    广播信息,即速度快捷.迅速及时.简明扼要的把信息发送给接收者. 当然在SNF快速开发平台上你也可以作为公告使用.不管当做什么使用要满足以下需求: 简单操作:页面操作简单 只需要输入内容就可以发送. 灵 ...

  6. Linux下通用打印系统CUPS使用教程

    昨天研究了一下关于在Linux下实现打印操作的相关内容,整理记录如下: 1.什么是CUPS CUPS(Common UNIX Printing System,即通用Unix打印系统)是FedoraCo ...

  7. 7-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案安全篇(GPRS模块SSL连接MQTT)

    6-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案安全篇(Wi-Fi模块SSL连接MQTT) 由于GPRS是直接和GPRS基站进行连接,其实对于GPRS而言,即使不加 ...

  8. 释放至强平台 AI 加速潜能 汇医慧影打造全周期 AI 医学影像解决方案

    基于英特尔架构实现软硬协同加速,显著提升新冠肺炎.乳腺癌等疾病的检测和筛查效率,并帮助医疗科研平台预防"维度灾难"问题 <PAGE 1 LEFT COLUMN: CUSTOM ...

  9. 基于cornerstone.js的dicom医学影像查看浏览功能

    最近由于项目需求,需要医学影像.dcm文件的预览功能,功能完成后,基于原生Demo做一个开源分享. 心急的小伙伴可以先看如下基于原生js的全部代码: 一.全部代码 <!DOCTYPE html& ...

随机推荐

  1. vue版本一直是2.9.6版本,卸载也卸载不掉,更新也更新不了

    原文链接:https://blog.csdn.net/zlzbt/article/details/110136755 主要是找到本地文件 E:\StudyFile\VueStudy λ where v ...

  2. Mac创建Root用户

    1.打开Mac终端管理工具 前往-实用工具-终端 2.用命令的形式创建账户 sudo passwd root 3.输入当前登录用户密码 4.输入root用户密码并验证

  3. HDOJ-1686(KMP算法)

    Oulipo HDOJ-1686 本题的思路就是KMP,和HDOJ-1711思路一样,不再赘述详情可以看链接:1711题解 #include<iostream> #include<c ...

  4. HDOJ-6681(离散化+线段树)

    Rikka With Cake HDOJ-6681 最终的答案为射线的交点数加一.当然,我们也可以证明.证明需要用到欧拉公式 V−E+F=2 V-E+F=2V−E+F=2 .设射线的交点共 c cc ...

  5. Excel_不打开文件进行跨工作簿查询

    在使用Excel时,我们经常会遇到这种问题,我的数据源在表1里面,但是我要在表2里面做报表,用lookup和offset等公式都需要打开表1操作,否则就会报错.那么有没有办法在不打开表1的情况下在表2 ...

  6. 快速查找未打补丁的exp

    在windows DOS窗口下输入以下内容,输出为未打的补丁信息列表 systeminfo>vul.txt&(for %i in (KB977165 KB2160329 KB250366 ...

  7. Kettle连接数据库失败

    Kettle是使用Java开发,开源的一款ETL工具,这里记录一下关于Kettle有关于数据库连接的问题 1.mysql版本需要注意区分,在mysql8.0的文档中官方已经给出,使用caching_s ...

  8. CF557E Ann and Half-Palindrome 题解

    算法:dp+字典树 题目链接Ann and Half-Palindrome   在CF刷字符串题的时候遇到了这题,其实并没有黑题这么难,个人感觉最多是紫题吧(虽然一开始以为是后缀自动机的神仙题).   ...

  9. 2019 南京网络赛 B super_log 【递归欧拉降幂】

    一.题目 super_log 二.分析 公式很好推出来,就是$$a^{a^{a^{a^{...}}}}$$一共是$b$个$a$. 对于上式,由于指数太大,需要降幂,这里需要用到扩展欧拉定理: 用这个定 ...

  10. VS2013环境下配置OSG(3.4.0版本)

    参考链接1: http://blog.csdn.net/lonsegdi/article/details/50579439 参考链接2: http://bbs.osgchina.org/forum.p ...