getclassname

本文介绍了一个用于获取指定窗口类名的API函数——GetClassName。该函数通过提供窗口句柄来获取对应的类名,并将类名存储在一个指定的缓冲区中。文章详细解释了函数的参数含义及返回值的意义。
  name="google_ads_frame" marginwidth="0" marginheight="0" src="http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-5572165936844014&dt=1193665761703&lmt=1193665780&format=336x280_as&output=html&correlator=1193665761687&url=http%3A%2F%2Fwww.codeguru.cn%2Fpublic%2Fiframe%2Fwinapiiframe.htm&color_bg=FFFFFF&color_text=000000&color_link=000000&color_url=FFFFFF&color_border=FFFFFF&ad_type=text&ga_vid=1285758818.1193665762&ga_sid=1193665762&ga_hid=111695597&flash=9&u_h=768&u_w=1024&u_ah=740&u_aw=1024&u_cd=32&u_tz=480&u_his=8&u_java=true" frameborder="0" width="336" scrolling="no" height="280" allowtransparency="allowtransparency">     函数功能:该函数获得指定窗口所属的类的类名。

    函数原型:Int GetClassName(HWND hWnd,LPTSTR IpClassName int nMaxCount);参数:

    hWnd:窗口的句柄及间接给出的窗口所属的类。

    IpClassName:指向接收窗口类名字符串的缓冲区的指针。

    nMaxCount:指定由参数lpClassName指示的缓冲区的字节数。如果类名字符串大于缓冲区的长度,则多出的部分被截断。

    返回值:如果函数成功,返回值为拷贝到指定缓冲区的字符个数:如果函数失败,返回值为0。若想获得更多错误信息,请调用GetLastError函数。

    速查:Windows NT:3.1以上版本:Windows:95以上版本;Windows CE1.0以上版本;头文件:winuser.h库文件:user32.lib; Unicode:在 Windows NT上实现为 Unicode和 ANSI两种版本。

public void assignTasks(List orderList, List lineGroupSequences, List groupList, Map<String, Map<String, Map<String, Set>>> assignTeamResult, Map<String, Map<Date, Integer>> remainingTimeMap, Map<String, MrpListDTO> keyClassNameMap) { // 按产线分组的可用班组, 并按优先级排序 Map<String, List<PpLineGroupSequence>> lineGroupMap = lineGroupSequences.stream() .collect(Collectors.groupingBy( PpLineGroupSequence::getLine, Collectors.collectingAndThen( Collectors.toList(), list -> { list.sort(Comparator.comparingInt(PpLineGroupSequence::getSequence)); return list; } ) )); // 记录<工单号:占用时间> Map<String, BigDecimal> orderTotalTimeMap = orderList .stream() .filter(it -> !PpShiftTypeEnum.换型班次.getCode().equals(it.getShiftType())) .collect(Collectors.toMap( MrpListDTO::getOrderNo, MrpListDTO::getTotalTime, (existing, replacement) -> existing // 这里简单地保留现有的值,可根据需求修改 )); // 记录 <班组_需求日期_className> 的组合已经排满 Set<String> filledClasses = new HashSet<>(); // 记录锁定工单 <产线_班组_需求日期_班次 : 开工时间_完工时间> 的组合已经排的 Map<String, Set<String>> filledClasses2 = new HashMap<>(); // 产线不允许排的日期的班次<line, <date, className>> Map<String, Map<Date, List<String>>> tem = new HashMap<>(); // 限制任务调整取舍百分比 BigDecimal minPercentage = BigDecimalUtils.getDecimal(redisService.getCacheObject(CacheConstants.SYS_CONFIG_KEY + CacheConstants.PP_OVER_FLOW_RATE), BigDecimal.valueOf(0.2)); // 缓存的可能是没有除以100 minPercentage = minPercentage.compareTo(BigDecimal.ONE) > 0 ? minPercentage.divide(BigDecimal.valueOf(100), 1, RoundingMode.HALF_UP) : minPercentage; ListIterator<MrpListDTO> iterator = orderList.listIterator(); MrpListDTO prevOrder = null; while (iterator.hasNext()) { int currentIndex = iterator.nextIndex(); MrpListDTO order = iterator.next(); if (currentIndex < 0 || currentIndex > orderList.size()) { throw new IllegalArgumentException("currentIndex 超出范围"); } String oee = order.getOee(); String ct = order.getCt(); String line = order.getLine(); Date demandDate = order.getDemandDate(); BigDecimal orginQty = order.getQty(); BigDecimal totalDemandTime = order.getTotalTime(); String finishedProductNo = order.getFinishedProductNo(); String orderNo = order.getOrderNo(); String lockOrder = order.getLockOrder(); BigDecimal orderTotalTime = orderTotalTimeMap.get(orderNo); if (orderTotalTime == null) { continue; } BigDecimal minutesQty = BigDecimal.ONE.multiply(BigDecimalUtils.getDecimal(oee)).divide(BigDecimalUtils.getDecimal(ct), 6, RoundingMode.HALF_UP); // 获取该产线可用的班组列表, 并按优先级排序 List<PpLineGroupSequence> availableGroups = lineGroupMap.getOrDefault(line, Collections.emptyList()); if (availableGroups.isEmpty()) { throw new ServiceException(String.format("%s产线未配置班组,匹配失败", line)); } // 过滤只属于这条产线的班组日历 List<String> groupNos = availableGroups.stream().map(PpLineGroupSequence::getGroupNo).collect(Collectors.toList()); List<PpGroupScheduleDTO> newGroupList = groupList.stream().filter(it -> groupNos.contains(it.getGroupNo())).collect(Collectors.toList()); // 匹配最佳班组 List<MrpListDTO> prevList = new ArrayList<>(orderList.subList(0, currentIndex)); PpGroupScheduleDTO bestGroup = this.findBestGroup(prevList, order, availableGroups, newGroupList, remainingTimeMap, filledClasses, filledClasses2, tem); if (bestGroup == null) { String dateTime = DateUtils.dateTime(demandDate); throw new ServiceException(String.format("[%s]产线匹配班组[%s]日历失败, 请检查班组排班数是否满足排产后所需的班组数以及班组排班白晚班分配是否合理", line, dateTime)); // System.out.printf(“[%s]产线匹配班组[%s]日历失败, 请检查班组排班数是否满足排产后所需的班组数以及班组排班白晚班分配是否合理%n”, line, dateTime); // continue; } Map<Date, Integer> groupRemainingTime = remainingTimeMap.computeIfAbsent(bestGroup.getGroupNo(), k -> new HashMap<>()); int groupRemaining = groupRemainingTime.computeIfAbsent(bestGroup.getDate(), k -> 660); String key = bestGroup.getGroupNo() + "_" + DateUtils.dateTime(bestGroup.getDate()) + "_" + bestGroup.getClassName(); // 锁定工单, 这里的锁定工单用的是锁定工单明细, 所以有具体的白晚班 if (PpOrderLockStatus.LOCKED.getCode().equals(lockOrder)) { String key2 = bestGroup.getGroupNo() + "_" + DateUtils.dateTime(bestGroup.getDate()) + "_" + bestGroup.getClassName(); String startTime = DateUtils.format(order.getStartTime(), DateUtils.YYYY_MM_DD_HH_MM_SS); String endTime = DateUtils.format(order.getEndTime(), DateUtils.YYYY_MM_DD_HH_MM_SS); String value = startTime + "_" + endTime; filledClasses2.computeIfAbsent(key2, k -> new HashSet<>()).add(value); } if (totalDemandTime.intValue() <= groupRemaining) { // 需求时间小于等于剩余时间, 直接分配 int remaining = groupRemaining - totalDemandTime.intValue(); groupRemainingTime.put(bestGroup.getDate(), remaining); order.setTeamNo(bestGroup.getGroupNo()); order.setTeamDate(bestGroup.getDate()); order.setClassName(bestGroup.getClassName()); if (groupRemaining == totalDemandTime.intValue()) { // 该班组排满, 记录排满信息 filledClasses.add(key); } //排了这一单, 没到下班时间 if (remaining > 0) { // 如果此时是换型工单或者TMC类型, 就不用补了 if (PpShiftTypeEnum.换型班次.getCode().equals(order.getShiftType()) || PpOrderTypeEnum.TMC.getCode().equals(order.getType()) || PpOrderLockStatus.LOCKED.getCode().equals(lockOrder)) { System.out.println("换型工单/TMC工单/锁定不用考虑"); } else { // 计算比例: 距离下班时间的分钟数 ÷ 工单总用时 BigDecimal ratio = BigDecimal.valueOf(remaining).divide(orderTotalTime, 2, RoundingMode.HALF_UP).abs(); // 调整数量补充 BigDecimal qty = BigDecimal.valueOf(remaining).multiply(minutesQty).setScale(0, RoundingMode.HALF_UP); // < 0.2 补充 if (ratio.compareTo(minPercentage) <= 0) { System.out.println("< 0.2 补充 " + ratio); // 补充数量不能超过 (未来28天的需求量(不含当天) + 当天需求量 - 现有库存数量(触发任务前的 endStock)) BigDecimal demand1 = order.getDemand1(); BigDecimal demand3 = order.getDemand3(); BigDecimal preStock = order.getPreStock(); BigDecimal subtract = demand1.add(demand3).subtract(preStock); // 超过就用差值数量, 没超过就用补充数量 if (qty.compareTo(subtract) > 0) { order.setAddQty(order.getAddQty().add(subtract)); } else { order.setAddQty(order.getAddQty().add(qty)); } order.setTotalTime(order.getTotalTime().add(BigDecimal.valueOf(remaining))); // 班组占用情况也要更新 groupRemainingTime.put(bestGroup.getDate(), 0); filledClasses.add(key); } } } } else { // 如果此时是换型工单, 就不用拆了, 但是班组要占满 if (PpShiftTypeEnum.换型班次.getCode().equals(order.getShiftType()) || PpOrderLockStatus.LOCKED.getCode().equals(lockOrder)) { order.setTeamNo(bestGroup.getGroupNo()); order.setTeamDate(bestGroup.getDate()); order.setClassName(bestGroup.getClassName()); // 该班组排满,记录排满信息 groupRemainingTime.put(bestGroup.getDate(), 0); filledClasses.add(key); } else { // 需求时间大于剩余时间, 填满当前班组, 创建新任务 BigDecimal usedTime = BigDecimal.valueOf(groupRemaining); BigDecimal overtimeMinutes = totalDemandTime.subtract(usedTime); order.setTeamNo(bestGroup.getGroupNo()); order.setTeamDate(bestGroup.getDate()); order.setClassName(bestGroup.getClassName()); order.setTotalTime(usedTime); // 重新计算数量 // order.setQty(usedTime.multiply(minutesQty).setScale(0, RoundingMode.HALF_UP)); order.setAddQty(usedTime.multiply(minutesQty).setScale(0, RoundingMode.HALF_UP)); // 该班组排满,记录排满信息 groupRemainingTime.put(bestGroup.getDate(), 0); filledClasses.add(key); // 计算比例: 距离下班时间的分钟数 ÷ 工单总用时 BigDecimal ratio = overtimeMinutes.divide(orderTotalTime, 2, RoundingMode.HALF_UP).abs(); BigDecimal qty = overtimeMinutes.multiply(minutesQty).setScale(0, RoundingMode.HALF_UP); System.out.println("距离下班时间的分钟数 " + overtimeMinutes + " 比例 " + ratio); //TMC工单直接拆 if (PpOrderTypeEnum.TMC.getCode().equals(order.getType())) { // 超出部分新建一条工单 MrpListDTO newOrder = new MrpListDTO(); BeanUtils.copyBeanProp(newOrder, order); newOrder.setTotalTime(overtimeMinutes); // newOrder.setQty(qty); newOrder.setAddQty(qty); newOrder.setId(null); newOrder.setTeamNo(null); newOrder.setTeamDate(null); newOrder.setClassName(null); iterator.add(newOrder); // 回退迭代器,以便下一轮处理这个新插入的工单 if (iterator.hasPrevious()) { iterator.previous(); } } else { // 其他类型的工单 还要算一下比例 // > 0.2 拆单; < 0.2 舍弃 if (ratio.compareTo(minPercentage) > 0) { System.out.println("> 0.2 拆单 " + ratio); // 超出部分新建一条工单 MrpListDTO newOrder = new MrpListDTO(); BeanUtils.copyBeanProp(newOrder, order); newOrder.setTotalTime(overtimeMinutes); // newOrder.setQty(qty); newOrder.setAddQty(qty); newOrder.setId(null); newOrder.setTeamNo(null); newOrder.setTeamDate(null); newOrder.setClassName(null); iterator.add(newOrder); // 回退迭代器,以便下一轮处理这个新插入的工单 if (iterator.hasPrevious()) { iterator.previous(); } } else if (ratio.compareTo(minPercentage) <= 0) { System.out.println("< 0.2 舍弃 " + ratio); } } } } String keyClassName = order.getClassName() + order.getTeamNo() + DateUtils.dateTime(order.getTeamDate()); MrpListDTO _prevOrder = keyClassNameMap.get(keyClassName); // 锁定工单不需要设置开工和完工时间 if (!PpOrderLockStatus.LOCKED.getCode().equals(lockOrder)) { //单次设置开工和完工时间 this.setStartEndTime(order, _prevOrder, filledClasses2, iterator); } keyClassNameMap.put(keyClassName, order); // 填充 assignTeamResult String teamNo = order.getTeamNo(); String className = order.getClassName(); String dateStr = DateUtils.dateTime(order.getTeamDate()); if (StringUtils.isEmpty(teamNo) || StringUtils.isEmpty(className) || StringUtils.isEmpty(dateStr)) { continue; // 跳过处理 } AssignLineOrderDTO assignLineOrder = new AssignLineOrderDTO(order.getOrderNo(), order.getLine()); assignTeamResult.computeIfAbsent(teamNo, k -> new LinkedHashMap<>()) .computeIfAbsent(className, k -> new LinkedHashMap<>()) .computeIfAbsent(dateStr, k -> new HashSet<>()) .add(assignLineOrder); prevOrder = order; } } private void setStartEndTime(MrpListDTO order, MrpListDTO prevOrder, Map<String, Set> filledClasses, ListIterator iterator) { LocalDate groupDate = order.getTeamDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); boolean isDayShift = order.getClassName().contains(“白班”); boolean isNightShift = order.getClassName().contains(“晚班”); List<MrpListDTO> tem = new ArrayList<>(); if (!isDayShift && !isNightShift) { throw new IllegalArgumentException("计算开工/完工时间时, 发现无效的班次名称: " + order.getClassName()); } // 班次时间窗口:起始与结束(考虑跨天) LocalDateTime shiftStart; LocalDateTime shiftEnd; if (isDayShift) { shiftStart = LocalDateTime.of(groupDate, DAY_SHIFT_START); shiftEnd = LocalDateTime.of(groupDate, DAY_SHIFT_END); } else { // 晚班 shiftStart = LocalDateTime.of(groupDate, NIGHT_SHIFT_START); shiftEnd = LocalDateTime.of(groupDate.plusDays(1), NIGHT_SHIFT_END); } BigDecimal totalTime = order.getTotalTime(); int totalMinutes = totalTime.intValue(); Duration requiredDuration = Duration.ofMinutes(totalMinutes); LocalDateTime startTime = null; LocalDateTime endTime = null; String key2 = null; Set<String> values = null; // 第一条数据:从班次开始时间排 if (prevOrder == null) { startTime = shiftStart; } // 存在前序任务,但没有被占时间段,则从上一个任务结束时间开始 else { key2 = order.getTeamNo() + "_" + DateUtils.dateTime(order.getTeamDate()) + "_" + order.getClassName(); values = filledClasses.get(key2); // 如果有被占时间段,需基于空闲时间段安排 if (!CollectionUtils.isEmpty(values)) { // 解析 occupiedPeriods 并排序 List<Interval> occupiedPeriods = new ArrayList<>(); for (String value : values) { String[] parts = value.split("_"); if (parts.length != 2) { continue; } LocalDateTime start = LocalDateTime.parse(parts[0], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); LocalDateTime end = LocalDateTime.parse(parts[1], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); occupiedPeriods.add(new Interval(start, end)); } occupiedPeriods.sort(Comparator.comparing(Interval::start)); // 计算空闲时间段 List<Interval> freePeriods = calculateFreePeriods(shiftStart, shiftEnd, occupiedPeriods); // 找到第一个能放下任务的空闲段 for (Interval free : freePeriods) { LocalDateTime freeStart = free.start(); LocalDateTime freeEnd = free.end(); Duration freeDuration = Duration.between(freeStart, freeEnd); if (freeDuration.compareTo(requiredDuration) >= 0) { startTime = freeStart; break; } else { // 截断 startTime = freeStart; endTime = freeEnd; // 用完整个空闲段 // 创建剩余任务 // 本次占用时间 long allocatedMinutes = freeDuration.toMinutes(); // 剩余占用时间 long remainingMinutes = requiredDuration.toMinutes() - allocatedMinutes; String oee = order.getOee(); String ct = order.getCt(); BigDecimal minutesQty = BigDecimal.ONE.multiply(BigDecimalUtils.getDecimal(oee)).divide(BigDecimalUtils.getDecimal(ct), 6, RoundingMode.HALF_UP); BigDecimal qty = BigDecimal.valueOf(allocatedMinutes).multiply(minutesQty).setScale(0, RoundingMode.HALF_UP); BigDecimal qty2 = BigDecimal.valueOf(remainingMinutes).multiply(minutesQty).setScale(0, RoundingMode.HALF_UP); // 原工单要变 order.setTotalTime(BigDecimal.valueOf(allocatedMinutes)); order.setAddQty(qty); requiredDuration = Duration.ofMinutes(allocatedMinutes); // 创建新工单, 不需要再匹配班组 MrpListDTO newOrder = new MrpListDTO(); BeanUtils.copyProperties(order, newOrder); newOrder.setTotalTime(BigDecimal.valueOf(remainingMinutes)); newOrder.setAddQty(qty2); tem.add(newOrder); break; // 当前段只处理这一部分 } } // 若无合适空闲段,则从 shiftStart 开始(或抛异常/排队到下一个班次?可扩展) if (startTime == null) { throw new IllegalStateException("无足够空闲时间安排任务"); } } // 无占用,则从上一个任务结束时间开始 else { startTime = prevOrder.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); } } // 现在有了 startTime,计算不考虑休息的 endTime endTime = startTime.plus(requiredDuration); // 考虑休息时间暂停(假设 BREAK_TIMES 是每日固定休息点,如 [12:00, 17:00] 等) LocalDateTime _endTime = handleBreakTimes(startTime, endTime, 1); // 设置最终时间 order.setStartTime(Date.from(startTime.atZone(ZoneId.systemDefault()).toInstant())); order.setEndTime(Date.from(_endTime.atZone(ZoneId.systemDefault()).toInstant())); // 新的占用时间范围 String newOccupiedPeriod = startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "_" + _endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); if (StringUtils.isNotEmpty(key2) && values != null) { values.add(newOccupiedPeriod); } // 截断的新建工单 if (!tem.isEmpty()) { for (MrpListDTO newOrder : tem) { setStartEndTime(newOrder, order, filledClasses, iterator); iterator.add(newOrder); } } } 因为我的操作是先把锁定工单找出来分配完班组, 记录占用的时间段, filledClasses2. 在匹配未锁定工单, 如果有匹配到锁定工单已占用但是未占满的班组时, 计算可用的时间段分配.现在有个问题, 工单之间存在换型, 如果本条和前一条换型有就要插入换型工单先于本条处理. 因为锁定工单先分配了时间, 当本条恰好和锁定工单为前后条时, 需要考虑换型的情况, 纠正一个误区, 非锁定不一定就跟在锁定后面, 锁定有可能班组是中间时间段锁定,前后能用, 那么前后可能是不同的非锁定工单, 并且, 也存在锁定工单锁了整个班组, 那么非锁定工单分配的班组在这条锁定工单班组前后的情况, 也需要考虑有无换型. 如果有, 那么非锁定工单可能要截断 , 截断部分就是换型时长, 截断部分回退重新处理. 这条换型工单新建时长就是这条非锁定的被截断部分
最新发布
11-08
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值