- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我尝试遵循 Allen Denver 的 article实现异步串口I/O。本文没有提到如何或在何处以有用的方式调用主程序循环中的函数。将它们放入每秒返回的循环中后,很明显不需要定期调用 ReadFile()。我尝试将 WaitCommEvent() 放入循环中,以便仅在字符到达端口时才会进行读取。这导致了一系列错误。在尝试将代码简化为我可以在此处发布的内容时,即使我尝试以重叠模式打开文件也开始失败,因此我似乎无法发布有用的示例。但是,我将发布类似的基本概念,即如果我可以简单地用异步事件(例如串行端口上显示的字符)触发读取和写入,那么我并不真正关心读取和写入是否必须同步。 Allen Denver 文章中的异步函数相当复杂,从他的示例中我不清楚如何触发对到达端口的字符的读取。
在下面的代码中,在 while(1) 循环的主体中注释掉了五行,我试图在其中等待字符到达。即使端口以重叠模式(在原始代码中)打开,并且发送和接收函数都有自己的重叠结构,WaitCommEvent() 错误似乎引用了待处理的 I/O。解决这个问题的正确方法是什么?
/* WINSIO.c 2020-01-22 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int ConfigureSerialPort(HANDLE hPort)
{
int Status;
DCB dcb = {0};
COMMTIMEOUTS timeouts;
dcb.DCBlength = sizeof(dcb);
Status = GetCommTimeouts(hPort, &timeouts);
GetCommTimeouts(hPort, &timeouts);
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 50;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts(hPort, &timeouts)) {
printf("Error setting timeouts on port!\n");
}
Status = GetCommState(hPort, &dcb);
dcb.BaudRate = 19200;
dcb.Parity = NOPARITY;
dcb.fBinary = TRUE; // Binary mode; no EOF check
dcb.fParity = FALSE; // Enable parity checking
dcb.fOutxCtsFlow = FALSE; // No CTS output flow control
dcb.fOutxDsrFlow = FALSE; // No DSR output flow control
dcb.fDtrControl = DTR_CONTROL_DISABLE; // DTR flow control type
dcb.fDsrSensitivity = FALSE; // DSR sensitivity
dcb.fTXContinueOnXoff = FALSE; // XOFF continues Tx
dcb.fOutX = FALSE; // No XON/XOFF out flow control
dcb.fInX = FALSE; // No XON/XOFF in flow control
dcb.fErrorChar = FALSE; // Disable error replacement
dcb.fNull = FALSE; // Disable null stripping
dcb.fRtsControl = RTS_CONTROL_DISABLE; // RTS flow control
dcb.fAbortOnError = FALSE; // Do not abort reads/writes on err
dcb.ByteSize = 8; // Number of bits/byte, 4-8
dcb.StopBits = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2
dcb.EvtChar = 0x84; // 'T'
if (!SetCommState (hPort, &dcb)) {
printf("Unable to configure serial port!\n");
}
return 0;
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sendpckt(HANDLE hComm, unsigned length, unsigned char * pckt)
{
unsigned long NbytesWritten = 0;
int result;
DWORD dwCommEvent;
OVERLAPPED oWrite;
oWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (oWrite.hEvent == NULL)
return FALSE; // Error creating overlapped event handle.
result = WriteFile(hComm, pckt, length, &NbytesWritten, NULL);
//result = WriteFile(hComm, pckt, length, &NbytesWritten, &oWrite);
if (!result) printf("Err: %d\n", GetLastError());
WaitCommEvent(hComm, &dwCommEvent, &oWrite);
// printf("Wrote? %d:%d\n", result, NbytesWritten);
CloseHandle(oWrite.hEvent);
return 0;
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int recvpckt(HANDLE hComm, unsigned char * pckt)
{
int Status, idx = 0, len = 0;
unsigned long Nbytes;
unsigned char chRead;
OVERLAPPED oRead;
do {
//Status = ReadFile(hComm, &chRead, 1, &Nbytes, &oRead);
Status = ReadFile(hComm, &chRead, 1, &Nbytes, NULL);
if (Status) {
pckt[idx++] = chRead;
if(Nbytes > 0) len = idx;
}
}
while(Nbytes > 0);
return len;
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int args(int argc, char * argv[], char * port)
{
static int i;
i = atoi(argv[1]);
sprintf(port, "\\\\.\\COM%d", i);
return i;
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void main(int argc, char *argv[]) {
HANDLE hPort;
int result, len, Status;
DWORD dwCommEvent;
OVERLAPPED o;
unsigned idx = 0;
unsigned char TXBUF[] = "T", RXBUF[2048], port[64];
if (argc > 1) result = args(argc, argv, port);
SetConsoleTitle(port); // To specify serial port number on open
hPort = CreateFile (port, GENERIC_READ | GENERIC_WRITE, 0, NULL,
//OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
OPEN_EXISTING, 0, NULL);
ConfigureSerialPort(hPort);
if (hPort == INVALID_HANDLE_VALUE) {
printf("Error in openning serial port\n");
exit(0); // No point in going on if serial port didn't open
}
else
printf("Serial Port Open\n");
Status = SetCommMask(hPort, EV_RXCHAR);
if (Status == FALSE) printf("Error! Setting CommMask\n");
o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (o.hEvent == NULL) printf("Error creating overlapped event; abort.\n");
while (1) {
sendpckt(hPort, 1, TXBUF);
printf("Sending 0x%.2X\n", TXBUF[0]);
// Status = WaitCommEvent(hPort, &dwCommEvent, &o); // Wait for chars
// if (Status == FALSE)
// printf("Error Setting WaitCommEvent()%d\n", GetLastError());
// else { // If WaitCommEvent() == TRUE then Read the received data
// printf("Chars Recveived\n");
len = recvpckt(hPort, RXBUF);
if (len > 0)
{
printf("RCVD(%d): ", len);
}
for (idx=0; idx<len; idx++)
{
printf("%d:0x%.2X ", idx+1, RXBUF[idx]);
}
// }
SleepEx(1000, TRUE); // How often to look for data in RX buffer
}
CloseHandle(o.hEvent); // Close the Event Handle
CloseHandle(hPort); // Close the serial port
}
在 Rita Han 的非常感谢的反馈后发布额外的代码。从其他帖子中可以清楚地看出,我的同步示例没有阐明要点。因此,我附上了大部分可以工作的异步版本,但还有很多不足之处。如果它可以简化为 Rita Han 示例的长度,那就太棒了。此示例执行“功能”,这意味着它既发送又接收。问题是,正如最初所述,它需要定期轮询端口以查找存在的字符,这是一个巨大的阻力。以下代码与 Allen Denver 的代码几乎完全相同,它不提供我正在寻找的基于事件的响应,但它确实发送和接收字符。我目前正在通过带有两个串行端口的零调制解调器电缆运行它,因此该行为很容易观察到。通过更改 SleepEX() 语句上的超时值可以清楚地了解对轮询串行端口的依赖。尽管 Rita Han 的反馈很有用,但代码并未表现出我正在寻找的行为。如果有人可以采用以下示例,并使其响应到达串行端口的字符而不是等待轮询,那么这就是我正在寻找的。我需要使用 ReadFileEX() 吗?还有其他方法可以注册需要在这里混合的事件吗? Joseph M. Newcomer 在此 article 中折扣所有串行事件的使用说它们只是为了 16 位 Windows 兼容性而存在,然后继续提供了一个比 Allen Denver 所做的更复杂的串行端口编程示例。真的需要这么困难吗?
/* WINAIO.c 2020-01-22 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int ConfigureSerialPort(HANDLE hPort) {
int Status;
DCB dcb = {0};
COMMTIMEOUTS timeouts;
dcb.DCBlength = sizeof(dcb);
Status = GetCommTimeouts(hPort, & timeouts);
GetCommTimeouts(hPort, & timeouts);
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 50;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts(hPort, & timeouts)) {
printf("Error setting timeouts on port!\n");
}
Status = GetCommState(hPort, & dcb);
dcb.BaudRate = 19200;
dcb.Parity = NOPARITY;
dcb.fBinary = TRUE; // Binary mode; no EOF check
dcb.fParity = FALSE; // Enable parity checking
dcb.fOutxCtsFlow = FALSE; // No CTS output flow control
dcb.fOutxDsrFlow = FALSE; // No DSR output flow control
dcb.fDtrControl = DTR_CONTROL_DISABLE; // DTR flow control type
dcb.fDsrSensitivity = FALSE; // DSR sensitivity
dcb.fTXContinueOnXoff = FALSE; // XOFF continues Tx
dcb.fOutX = FALSE; // No XON/XOFF out flow control
dcb.fInX = FALSE; // No XON/XOFF in flow control
dcb.fErrorChar = FALSE; // Disable error replacement
dcb.fNull = FALSE; // Disable null stripping
dcb.fRtsControl = RTS_CONTROL_DISABLE; // RTS flow control
dcb.fAbortOnError = FALSE; // Do not abort reads/writes on err
dcb.ByteSize = 8; // Number of bits/byte, 4-8
dcb.StopBits = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2
dcb.EvtChar = 0x84; // 'T'
if (!SetCommState(hPort, & dcb)) {
printf("Unable to configure serial port!\n");
}
return 0;
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sendpckt(HANDLE hComm, unsigned length, unsigned char *pckt) {
unsigned long NbytesWritten = 0;
OVERLAPPED ovl = {0};
BOOL fRes;
ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ovl.hEvent == NULL)
return FALSE; // Error creating overlapped event handle.
//Issue Write.
if (!WriteFile(hComm, pckt, length, & NbytesWritten, & ovl)) {
if (GetLastError() != ERROR_IO_PENDING) {
fRes = FALSE; // WriteFile failed, but isn't delayed. Report error...
} else {
//Write is pending.
if (!GetOverlappedResult(hComm, & ovl, & NbytesWritten, TRUE))
fRes = FALSE;
else
fRes = TRUE;
}
} else // Write operation completed successfully.
fRes = TRUE;
// printf(" 0X%.2X ", chWrite);
CloseHandle(ovl.hEvent);
return fRes;
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int recvpckt(HANDLE hComm, unsigned char *pckt) {
# define READ_TIMEOUT 500 // milliseconds
int len = 0;
unsigned long Nbytes;
unsigned char chRead, BUF[2048];
BOOL fWaitingOnRead = FALSE;
OVERLAPPED ovl = {0};
DWORD dwRes;
/*
Status = SetCommMask(hComm, EV_RXFLAG);
if (Status == FALSE) printf("Error! Setting CommMask\n");
// else printf("Setting CommMask Succesful\n");
// */
ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ovl.hEvent == NULL) printf("Error creating overlapped event; abort.\n");
if (!fWaitingOnRead) {
// Issue read operation
if (!ReadFile(hComm, & BUF, 2048, & Nbytes, & ovl))
//if(!ReadFile(hComm, &chRead, 1, &Nbytes, &ovl))
{
if (GetLastError() != ERROR_IO_PENDING) // read not delayed?
// Error in communications; report it
printf("Error in Communications...\n");
else {
fWaitingOnRead = TRUE;
// printf("l:%d ", len); // shows loop alive
}
} else {
if (Nbytes > 0) {
// read completed immediately
memcpy(pckt, BUF, Nbytes);
len = Nbytes;
printf("Immediate Read Completion\n");
//HandleASuccessfulRead(lpbuf, dwRead);
}
}
}
if (fWaitingOnRead) {
dwRes = WaitForSingleObject(ovl.hEvent, READ_TIMEOUT);
switch (dwRes) {
// Read completed.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hComm, & ovl, & Nbytes, FALSE))
printf("Error in Communications Lower Portion\n");
// Error in communications; report it.
else {
if (Nbytes > 0) {
// Read completed successfully
// HandleASuccessfulRead(lpbuf, dwRead);
// Will run away and execute here every time
fWaitingOnRead = FALSE;
memcpy(pckt, BUF, Nbytes);
len = Nbytes;
printf("Read Completion After Wait\n");
}
}
case WAIT_TIMEOUT:
//printf("l:%d %d\n", len,rxstate);
// Operation isn't complete yet. fWaitingOnRead flag isn't changed
// since I'll loop back around, and I don't want to issue another read
// until the first one finishes.
// Good time to do some background work.
break;
default:
// Error in the WaitForSingleObject; abort.
// This indicates a problem with the OVERLAPPED structure's event handle
break;
}
}
CloseHandle(ovl.hEvent);
return Nbytes;
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int args(int argc, char *argv[], char *port) {
static int i;
i = atoi(argv[1]);
sprintf(port, "\\\\.\\COM%d", i);
return i;
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void main(int argc, char *argv[]) {
HANDLE hPort;
int result, len, Status;
DWORD dwCommEvent;
OVERLAPPED o;
unsigned idx = 0;
unsigned char TXBUF[] = "T", RXBUF[2048], port[64];
if (argc > 1) result = args(argc, argv, port);
SetConsoleTitle(port); // To specify serial port number on open
hPort = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
//OPEN_EXISTING, 0, NULL);
ConfigureSerialPort(hPort);
if (hPort == INVALID_HANDLE_VALUE) {
printf("Error in openning serial port\n");
exit(0); // No point in going on if serial port didn't open
} else
printf("Serial Port Open\n");
Status = SetCommMask(hPort, EV_RXCHAR);
if (Status == FALSE) printf("Error! Setting CommMask\n");
o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (o.hEvent == NULL) printf("Error creating overlapped event; abort.\n");
while (1) { // This is the loop for getting work done.
sendpckt(hPort, 1, TXBUF);
printf("Sending 0x%.2X\n", TXBUF[0]);
// Status = WaitCommEvent(hPort, &dwCommEvent, &o); // Wait for chars
// if (Status == FALSE)
// printf("Error Setting WaitCommEvent()%d\n", GetLastError());
// else { // If WaitCommEvent() == TRUE then Read the received data
// printf("Chars Recveived\n");
len = recvpckt(hPort, RXBUF);
if (len > 0) {
printf("RCVD(%d): ", len);
}
for (idx = 0; idx < len; idx++) {
printf("%d:0x%.2X ", idx + 1, RXBUF[idx]);
}
// }
SleepEx(1000, TRUE); // How often to look for data in RX buffer
// And how often to send data to the other port
}
CloseHandle(o.hEvent); // Close the Event Handle
CloseHandle(hPort); // Close the serial port
}
最佳答案
CreateFile
中的FILE_FLAG_OVERLAPPED
打开串行端口如果您想异步写入和读取。ReadFile
中的 lpNumberOfBytesRead
参数:如果这是异步操作,请使用 NULL
来避免此参数潜在的错误结果。您可以通过 OVERLAPPED 的 InternalHigh
检查读取长度.ReadFile
和 WriteFile
可能会导致错误代码ERROR_IO_PENDING
,这不是失败;它指示写入操作正在等待异步完成。以下是您可以引用的示例:
int sendpckt(HANDLE hComm, unsigned length, unsigned char * pckt)
{
BOOL result;
DWORD dwCommEvent;
OVERLAPPED oWrite = { 0 };
DWORD errCode;
result = SetCommMask(hComm, EV_TXEMPTY);
if (!result) printf("Err: %d\n", GetLastError());
result = WriteFile(hComm, pckt, length, NULL, &oWrite);
if (result == FALSE)
{
errCode = GetLastError();
if (errCode != ERROR_IO_PENDING)
printf("Error! Setting CommMask\n");
}
OVERLAPPED commOverlapped = { 0 };
commOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (commOverlapped.hEvent == NULL)
return FALSE; // Error creating overlapped event handle.
assert(commOverlapped.hEvent);
result = WaitCommEvent(hComm, &dwCommEvent, &commOverlapped);
if (!dwCommEvent)
printf("Error Setting WaitCommEvent()%d\n", GetLastError());
else
{
// If WaitCommEvent() == TRUE then Read the received data
if (dwCommEvent & EV_TXEMPTY)
{
printf("Send complete.\n");
}
}
CloseHandle(oWrite.hEvent);
CloseHandle(commOverlapped.hEvent);
return 0;
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int recvpckt(HANDLE hComm, unsigned char * pckt)
{
BOOL result;
int len = 0;
OVERLAPPED oRead = { 0 };
DWORD errCode;
DWORD dwCommEvent;
result = SetCommMask(hComm, EV_RXCHAR);
if (!result) printf("Err: %d\n", GetLastError());
result = ReadFile(hComm, pckt, 2048, NULL, &oRead);
if (result == FALSE)
{
errCode = GetLastError();
if (errCode != ERROR_IO_PENDING)
printf("nError! Setting CommMask\n");
}
OVERLAPPED commOverlapped = { 0 };
commOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (commOverlapped.hEvent == NULL)
return FALSE; // Error creating overlapped event handle.
assert(commOverlapped.hEvent);
result = WaitCommEvent(hComm, &dwCommEvent, &commOverlapped);
if (!dwCommEvent)
printf("Error Setting WaitCommEvent()%d\n", GetLastError());
else
{
if (dwCommEvent & EV_TXEMPTY)
{
printf("Chars Recveived\n");
len = oRead.InternalHigh;
}
}
CloseHandle(oRead.hEvent);
CloseHandle(commOverlapped.hEvent);
return len;
};
void main(int argc, char *argv[]) {
HANDLE hPort;
int len;
unsigned idx = 0;
unsigned char TXBUF[] = "T", RXBUF[2048], port[64] = "COM8";
SetConsoleTitle(port); // To specify serial port number on open
hPort = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
ConfigureSerialPort(hPort);
if (hPort == INVALID_HANDLE_VALUE) {
printf("Error in openning serial port\n");
exit(0); // No point in going on if serial port didn't open
}
else
printf("Serial Port Open\n");
while (1) {
sendpckt(hPort, 1, TXBUF);
printf("Sending 0x%.2X\n", TXBUF[0]);
len = recvpckt(hPort, RXBUF);
if (len > 0)
{
printf("RCVD(%d): \n", len);
}
for (idx = 0; idx < len; idx++)
{
printf("%d:0x%.2X \n", idx + 1, RXBUF[idx]);
}
SleepEx(1000, TRUE); // How often to look for data in RX buffer
}
CloseHandle(hPort); // Close the serial port
}
更新:
另一种方法是使用 WaitForSingleObject
没有 SetCommMask
和 WaitCommEvent
。以读操作为例:
int recvpckt(HANDLE hComm, unsigned char * pckt)
{
BOOL result;
int len = 0;
OVERLAPPED oRead = { 0 };
DWORD errCode;
DWORD dwCommEvent;
oRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (oRead.hEvent == NULL)
return FALSE; // Error creating overlapped event handle.
assert(oRead.hEvent);
result = ReadFile(hComm, pckt, 2048, NULL, &oRead);
if (result == FALSE)
{
errCode = GetLastError();
if (errCode != ERROR_IO_PENDING)
printf("nError! Setting CommMask\n");
}
DWORD dwWaitResult = WaitForSingleObject(oRead.hEvent, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
printf("Received.\n");
break;
case WAIT_TIMEOUT:
printf("Timeout.\n");
break;
case WAIT_FAILED:
printf("Failed.\n");
break;
case WAIT_ABANDONED:
printf("Abandoned.\n");
return FALSE;
}
CloseHandle(oRead.hEvent);
return len;
};
关于c - Win32 上的异步串行 I/O - 如何创建警报事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59867506/
我正在尝试将字符串转换为 float 。我知道 parseFloat() 可以做到这一点,但我也找到了下面的语法,但没有太多引用。 什么是正确的语法,因为它们似乎都有效。我可以在哪里了解更多相关信息?
我见过一些看起来很酷的“窗口”/“警报”/不管它们叫什么。我希望我知道。以下是其中的一些示例: 这些不应该是 Apple 独有的,因为我已经看到 3rd 方应用程序使用它们!我想知道这些 window
这个问题已经有答案了: What is the difference between a function call and function reference? (6 个回答) 已关闭 7 年前。
alert('test1'); var re = new RegExp("(http://(?:[A-Za-z0-9-]+\\.)?[A-Za-z0-9-]+\\.[A-Za-z0-9-]+/?)",
我有一个 Rails 应用程序,它与其他 Rails 应用程序通信以进行数据插入。我使用 jQuery $.post 方法进行数据插入。对于插入,我的其他 Rails 应用程序显示 200 OK。但在
我的作业有问题...我不知道我的代码有什么问题..我的作业是创建一个简单的学习数学和级别选择......我使用下拉菜单来选择级别和算术运算......现在我的问题是,当我单击按钮时,它将转到函数sta
我有一些复选框,其值属性来自数据库。我希望用户始终检查具有相同值的复选框(如果他不使用 javascript 发出警报)。我尝试使用以下 javascript 代码执行此操作,但没有用 fu
这有点难以解释,我的网站上有一个幻灯片形式的多部分表单。他们必须使用单选按钮从 3/4 选项中进行选择。 我对它们进行了一些验证,以确保用户在允许转到下一张幻灯片之前选择一个。 如果我单击一个对象来选
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 5 年前。 Improve this ques
我的页面上有一个click链接,我想在单击时播放通知或提示音。我如何使用jQuery做到这一点? 在此先感谢... :) 炸药 最佳答案 使用 jQuery sound 插件。 关于javascrip
我正在尝试在 Excel 列中创建 VBA -Alert 弹出窗口。在基于某些计算的 Excel 工作表中,将计算一些增长%(H 列),如果增长%> 20%,则会生成一个警报弹出窗口,询问原因代码,需
当用户滚动到网页的特定部分时,如何使用 JavaScript 显示警报。我尝试通过检查 document.body.clientWidth = document.documentElement.cli
我正在尝试制作一个脚本,其中会弹出一个提示窗口询问问题,并根据其中的答案,会弹出一个警告框,指出答案有效或无效。在我的代码中,我的提示框有效,但我的警报框没有。有人可以帮我解决这个问题吗?非常感谢!!
我正在尝试 Grafana 的警报和通知功能,它看起来真的很棒。 松弛通知示例。 但是有一个大问题。它需要使用 S3 进行配置,这使得任何人都可以公开访问图像。对于那些不希望公开访问其图像的公司来说,
我想知道是否有任何方法可以在 adobe reader 中通知用户pdf 表单已提交到服务器?我正在提交一个正常的 http/html 形式到 php 脚本没什么大不了的,直接,但文档、论坛等似乎存在
在 TFS 中构建失败后,是否可以通过电子邮件获取构建成功的信息? 当构建失败时(我确实如此),我可以收到电子邮件。当构建成功时,我可以收到电子邮件。 但我需要知道构建不再失败。如果我收到构建失败的电
我需要一些帮助来理解 jQuery 如何存储元素。请看一下这个链接: http://jsfiddle.net/NubWC/ 我试图从所有具有特定类的标题标签中获取元素 id,并将其放入数组中,以便我可
我想做 alert(this) 来进行演示(想看看代码中不同位置的“this”是什么)。 有什么想法可以实现这一目标吗? 现在它只返回[object Object]? 最佳答案 这样做: consol
当出现警告框时,有什么方法可以阻止 Enter 键盘吗?因此用户需要按 Esc 键或单击 Ok 按钮来删除警报。 alert('Hello'); 最佳答案 正如我之前的评论所述,标准的 javas
我正在尝试在 javascript 中创建一个函数并传入参数“name”,然后当用户点击一张照片时,会出现一条警告,类似于“这张照片是在 ____ 拍摄的” function photoWhere
我是一名优秀的程序员,十分优秀!