我正在设置一个小测试,其中包括供学生写下答案的空框。
这些框从页面上的不同位置开始,但为了整洁,我希望每个框都到达行尾。我正在使用
\newcommand{\answerbox[2]{\raisebox{2mm}{%
\fbox{%
\begin{minipage}[t]{#1}%
\hfill\vspace*{#2}%
\end{minipage}
}
}
}
效果很好,但我必须猜测框的宽度(第一个参数)。有没有巧妙的方法使用规则并hfill
做到这一点?
答案1
希望有人能来改进这一点。但这只是一个开始。
一个技巧是使用构造:
$$\xdef\pds{\the\predisplaysize}$$
这将获取到上一行结束处的宽度(进行了一些调整,有关详细信息,请参阅“TeX by Topic”的第 24.3 节)。这似乎是一种奇怪的方法,但这就是如何将其付诸实践:
\newcommand\answerbox[1]{%%
\bgroup
\abovedisplayskip0pt%%
\belowdisplayskip0pt%%
\abovedisplayshortskip0pt%%
\belowdisplayshortskip0pt%%
$$\xdef\pds{\the\predisplaysize}$$%
\par\prevdepth0pt{\par\kern-2\baselineskip\parskip0pt}%%
\noindent
\kern\pds\kern-2em\fbox{%%
\rule{\dimexpr\linewidth-\pds+2em-2\fboxrule-2\fboxsep}{0pt}%%
\rule{0pt}{#1}}%%
\egroup}
在此,分组是必要的,以将\abovedisplayskip
等的调整值限制在宏的范围内。
关于的调整2em
,请参见 TeX by Topic 的第 24.3 节。
\documentclass{article}
\usepackage{pgffor}
\setlength\parindent{0pt}
\usepackage{lipsum}
\newcommand\answerbox[1]{%%
\bgroup
\abovedisplayskip0pt%%
\belowdisplayskip0pt%%
\abovedisplayshortskip0pt%%
\belowdisplayshortskip0pt%%
$$\xdef\pds{\the\predisplaysize}$$%
\par\prevdepth0pt{\par\kern-2\baselineskip\parskip0pt}%%
\noindent
\kern\pds\kern-2em\fbox{%%
\rule{\dimexpr\linewidth-\pds+2em-2\fboxrule-2\fboxsep}{0pt}%%
\rule{0pt}{#1}}%%
\egroup}
\begin{document}
\foreach \myn in {0,5,10,15,20,25}
{
\par
\foreach \myk in {0,...,\myn} {a }%%
\answerbox{2ex}\vspace{2ex}%%
}
\lipsum[1-2]
\end{document}
pgffor
和的使用lipsum
仅仅是为了演示,对于宏来说不是必需的\answerbox
。
答案2
您可以\linegoal
使用linegoal
包中计算剩余空间(编译两次文档):
\documentclass{article}
\usepackage{linegoal}
\usepackage{lipsum}% just to have filler text
\newcommand\answerbox[1][0.5\ht\strutbox]{\raisebox{0.25\height}{%
\fbox{\begin{minipage}[t]{\dimexpr-\fboxsep-\fboxrule+\linegoal\relax}%
\mbox{}\rule{0pt}{#1}%
\end{minipage}%
}%
}%
}
\begin{document}
\noindent
test \answerbox
\noindent
other test text \answerbox
\noindent
some other test with a longer text \answerbox
\lipsum[4]
\end{document}
答案3
这里我使用 制作了一个盒子\cleaders
。参数\boxht
、\boxdp
和\rulewidth
可由用户设置。
为了确保框后不会挤入任何附加文本,后面\boxfill
应该跟一个\par
(正如我在这里所做的那样)或一个\\
。
已编辑,以消除对包的需要。
\documentclass{article}
\usepackage{lipsum}
\newcommand\rulewidth{1pt}
\newcommand\boxht{2ex}
\newcommand\boxdp{3pt}
\newcommand\boxfill{%
\let\replength\rulewidth
\def\laprule{\rule[-\boxdp]{\rulewidth}{\dimexpr\boxht+\boxdp+\rulewidth\relax}}%
\makebox[0pt][l]{\laprule}%
\cleaders\hbox to \replength{%
\ooalign{\rule[-\boxdp]{\replength}{\rulewidth}\cr%
\rule[\boxht]{\replength}{\rulewidth}}}\hfill%
\makebox[0pt][r]{\laprule}%
}
\begin{document}
A test\boxfill\par
This is another test of the fill when it doesn't begin on the first
line of a paragraph.\boxfill\par
\boxfill\par
\lipsum[1]
\end{document}
答案4
这里有一个zref
(模块savepos
)实现:
\documentclass{article}
\usepackage{zref-savepos,lipsum}
\newcounter{boxmarker}% Position marker counter
\newcommand{\boxfill}{%
\leavevmode% Just in case...
\stepcounter{boxmarker}% To avoid multiple references
\zsaveposx{boxmarkerL\theboxmarker}% Save left location
\hfill
\zsaveposx{boxmarkerR\theboxmarker}% Save right location
\llap{% Left overlap
\fbox{% framed box
\rule{0pt}{.5\baselineskip}% Vertical strut
\rule{\dimexpr\zposx{boxmarkerR\theboxmarker}sp-\zposx{boxmarkerL\theboxmarker}sp-2\fboxsep-2\fboxrule}{0pt}% Horizontal strut
}%
}%
}
\begin{document}
A test \boxfill
This is another test of the fill when it doesn't begin on the first
line of a paragraph. \boxfill
\boxfill
\lipsum[1]
\end{document}
上述方法使用了一些技术跳至行上的绝对位置。本质上,两个位置通过调用 进行标记和标注\boxfill
。这些<label>
s 将标记的 x 坐标存储在 中.aux
,通过 进行检索\zposx{<label>}
,然后用于计算线上的余数。
因为它使用 TeX 的\label
-\ref
系统,所以您必须在开始时至少编译两次,并且每次后续调整标记位置时也必须编译两次(以允许引用稳定下来)。